summaryrefslogtreecommitdiffstats
path: root/sys/v4l2
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2006-09-26 11:06:17 +0000
committerWim Taymans <wim.taymans@gmail.com>2006-09-26 11:06:17 +0000
commitb90e11a094296aaae07ff496b8b7631d4c96134a (patch)
tree0238633c646832d2d826da178c783398ff991018 /sys/v4l2
parent651b00563e2027f69e37a7d3a81c9d18498d451a (diff)
downloadgst-plugins-bad-b90e11a094296aaae07ff496b8b7631d4c96134a.tar.gz
gst-plugins-bad-b90e11a094296aaae07ff496b8b7631d4c96134a.tar.bz2
gst-plugins-bad-b90e11a094296aaae07ff496b8b7631d4c96134a.zip
sys/v4l2/: Fix pass at code cleanups, move errors cases out of the normal flow for additional code clarity.
Original commit message from CVS: * sys/v4l2/gstv4l2object.c: (gst_v4l2_class_probe_devices), (gst_v4l2_probe_needs_probe), (gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new), (gst_v4l2_object_destroy), (gst_v4l2_object_set_property_helper), (gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults), (gst_v4l2_object_start), (gst_v4l2_object_stop): * sys/v4l2/gstv4l2object.h: * sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init), (gst_v4l2src_init), (gst_v4l2src_dispose), (gst_v4l2src_set_property), (gst_v4l2src_get_property), (gst_v4l2src_fixate), (gst_v4l2src_get_caps), (gst_v4l2src_set_caps), (gst_v4l2src_get_read), (gst_v4l2src_get_mmap), (gst_v4l2src_create): * sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities), (gst_v4l2_open), (gst_v4l2_close), (gst_v4l2_get_norm), (gst_v4l2_set_norm), (gst_v4l2_get_frequency), (gst_v4l2_set_frequency), (gst_v4l2_signal_strength), (gst_v4l2_get_attribute), (gst_v4l2_set_attribute), (gst_v4l2_get_input), (gst_v4l2_set_input): * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list), (gst_v4l2src_queue_frame), (gst_v4l2src_grab_frame), (gst_v4l2src_get_capture), (gst_v4l2src_set_capture), (gst_v4l2src_capture_init), (gst_v4l2src_capture_start), (gst_v4l2src_capture_stop), (gst_v4l2src_capture_deinit), (gst_v4l2src_get_size_limits), (gst_v4l2src_set_fps), (gst_v4l2src_get_fps), (gst_v4l2src_buffer_finalize), (gst_v4l2src_buffer_new): Fix pass at code cleanups, move errors cases out of the normal flow for additional code clarity.
Diffstat (limited to 'sys/v4l2')
-rw-r--r--sys/v4l2/gstv4l2object.c53
-rw-r--r--sys/v4l2/gstv4l2object.h6
-rw-r--r--sys/v4l2/gstv4l2src.c113
-rw-r--r--sys/v4l2/v4l2_calls.c249
-rw-r--r--sys/v4l2/v4l2src_calls.c442
5 files changed, 510 insertions, 353 deletions
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index d67dfe53..bec30eb6 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -110,7 +110,6 @@ gst_v4l2_class_probe_devices (GstElementClass * klass, gboolean check,
g_free (device);
}
}
-
init = TRUE;
}
@@ -150,9 +149,7 @@ gst_v4l2_probe_needs_probe (GstPropertyProbe * probe,
G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
break;
}
-
return ret;
-
}
static GValueArray *
@@ -254,19 +251,18 @@ gst_v4l2_object_install_properties_helper (GObjectClass * gobject_class)
GST_TYPE_V4L2_DEVICE_FLAGS, 0, G_PARAM_READABLE));
g_object_class_install_property
(gobject_class, PROP_STD,
- g_param_spec_string ("std", "std",
- "standard (norm) to use", NULL, G_PARAM_READWRITE));
+ g_param_spec_string ("std", "Std",
+ "Standard (norm) to use", NULL, G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class, PROP_INPUT,
g_param_spec_string ("input",
- "input",
- "input/output (channel) to switch to", NULL, G_PARAM_READWRITE));
+ "Input",
+ "Input/output (channel) to switch to", NULL, G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class, PROP_FREQUENCY,
g_param_spec_ulong ("frequency",
- "frequency",
- "frequency to tune to (in Hz)", 0, G_MAXULONG, 0, G_PARAM_READWRITE));
-
+ "Frequency",
+ "Frequency to tune to (in Hz)", 0, G_MAXULONG, 0, G_PARAM_READWRITE));
}
GstV4l2Object *
@@ -275,13 +271,11 @@ gst_v4l2_object_new (GstElement * element,
GstV4l2SetInOutFunction set_in_out_func,
GstV4l2UpdateFpsFunction update_fps_func)
{
-
GstV4l2Object *v4l2object;
/*
* some default values
*/
-
v4l2object = g_new0 (GstV4l2Object, 1);
v4l2object->element = element;
@@ -300,16 +294,12 @@ gst_v4l2_object_new (GstElement * element,
v4l2object->xwindow_id = 0;
return v4l2object;
-
}
-
void
gst_v4l2_object_destroy (GstV4l2Object ** v4l2object)
{
-
if (*v4l2object) {
-
if ((*v4l2object)->videodev) {
g_free ((*v4l2object)->videodev);
(*v4l2object)->videodev = NULL;
@@ -317,29 +307,24 @@ gst_v4l2_object_destroy (GstV4l2Object ** v4l2object)
g_free (*v4l2object);
*v4l2object = NULL;
-
}
-
}
-
gboolean
gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
guint prop_id, const GValue * value, GParamSpec * pspec)
{
-
switch (prop_id) {
case PROP_DEVICE:
if (v4l2object->videodev)
g_free (v4l2object->videodev);
- v4l2object->videodev = g_strdup (g_value_get_string (value));
+ v4l2object->videodev = g_value_dup_string (value);
break;
case PROP_STD:
if (GST_V4L2_IS_OPEN (v4l2object)) {
GstTuner *tuner = GST_TUNER (v4l2object->element);
GstTunerNorm *norm = gst_tuner_find_norm_by_name (tuner,
- (gchar *)
- g_value_get_string (value));
+ (gchar *) g_value_get_string (value));
if (norm) {
/* like gst_tuner_set_norm (tuner, norm)
@@ -355,8 +340,7 @@ gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
if (GST_V4L2_IS_OPEN (v4l2object)) {
GstTuner *tuner = GST_TUNER (v4l2object->element);
GstTunerChannel *channel = gst_tuner_find_channel_by_name (tuner,
- (gchar *)
- g_value_get_string (value));
+ (gchar *) g_value_get_string (value));
if (channel) {
/* like gst_tuner_set_channel (tuner, channel)
@@ -389,9 +373,7 @@ gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
return FALSE;
break;
}
-
return TRUE;
-
}
@@ -405,15 +387,15 @@ gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
break;
case PROP_DEVICE_NAME:
{
- gchar *new = NULL;
+ const guchar *new = NULL;
if (GST_V4L2_IS_OPEN (v4l2object)) {
- new = (gchar *) v4l2object->vcap.card;
+ new = v4l2object->vcap.card;
} else if (gst_v4l2_open (v4l2object)) {
- new = (gchar *) v4l2object->vcap.card;
+ new = v4l2object->vcap.card;
gst_v4l2_close (v4l2object);
}
- g_value_set_string (value, new);
+ g_value_set_string (value, (gchar *) new);
break;
}
case PROP_FLAGS:
@@ -425,6 +407,8 @@ gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
(V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VIDEO_OUTPUT |
V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_TUNER | V4L2_CAP_AUDIO);
+ /* FIXME. if there is something with AUDIO we add something with
+ * video? this needs some explanation.. */
if (v4l2object->vcap.capabilities & V4L2_CAP_AUDIO)
flags |= V4L2_FBUF_CAP_CHROMAKEY;
}
@@ -444,9 +428,7 @@ gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
return FALSE;
break;
}
-
return TRUE;
-
}
static void
@@ -464,6 +446,7 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
norm =
GST_TUNER_NORM (gst_tuner_get_norm (GST_TUNER (v4l2object->element)));
if (norm) {
+ /* FIXME, free old? */
v4l2object->std = g_strdup (norm->label);
gst_tuner_norm_changed (tuner, norm);
g_object_notify (G_OBJECT (v4l2object->element), "std");
@@ -478,6 +461,7 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
channel =
GST_TUNER_CHANNEL (gst_tuner_get_channel (GST_TUNER (v4l2object->
element)));
+ /* FIXME, free old? */
v4l2object->input = g_strdup (channel->label);
gst_tuner_channel_changed (tuner, channel);
g_object_notify (G_OBJECT (v4l2object->element), "input");
@@ -498,7 +482,6 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
}
}
-
gboolean
gst_v4l2_object_start (GstV4l2Object * v4l2object)
{
@@ -507,7 +490,6 @@ gst_v4l2_object_start (GstV4l2Object * v4l2object)
else
return FALSE;
-
#ifdef HAVE_XVIDEO
gst_v4l2_xoverlay_start (v4l2object);
#endif
@@ -518,7 +500,6 @@ gst_v4l2_object_start (GstV4l2Object * v4l2object)
gboolean
gst_v4l2_object_stop (GstV4l2Object * v4l2object)
{
-
#ifdef HAVE_XVIDEO
gst_v4l2_xoverlay_stop (v4l2object);
#endif
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 54d799d4..2695abd3 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -99,21 +99,17 @@ struct _GstV4l2Object {
GstV4l2GetInOutFunction get_in_out_func;
GstV4l2SetInOutFunction set_in_out_func;
GstV4l2UpdateFpsFunction update_fps_func;
-
};
struct _GstV4l2ObjectClassHelper {
/* probed devices */
GList *devices;
-
};
-
GType gst_v4l2_object_get_type(void);
-
#define V4L2_STD_OBJECT_PROPS \
- PROP_DEVICE, \
+ PROP_DEVICE, \
PROP_DEVICE_NAME, \
PROP_FLAGS, \
PROP_STD, \
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index f652539e..0e5300e2 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -37,7 +37,7 @@
* <programlisting>
* gst-launch v4l2src use-fixed-fps=true ! xvimagesink
* </programlisting>
- * This exemple should be used to capture from web-cams
+ * This example should be used to capture from web-cams
* </para>
* </refsect2>
*/
@@ -130,7 +130,6 @@ static const guint32 gst_v4l2_formats[] = {
#endif
};
-
#define GST_V4L2_FORMAT_COUNT (G_N_ELEMENTS (gst_v4l2_formats))
GST_IMPLEMENT_V4L2_PROBE_METHODS (GstV4l2SrcClass, gst_v4l2src);
@@ -297,13 +296,11 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
pushsrc_class->create = gst_v4l2src_create;
gobject_class->dispose = gst_v4l2src_dispose;
-
}
static void
gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
{
-
v4l2src->v4l2object = gst_v4l2_object_new (GST_ELEMENT (v4l2src),
gst_v4l2_get_input, gst_v4l2_set_input, gst_v4l2src_update_fps);
@@ -335,8 +332,7 @@ gst_v4l2src_dispose (GObject * object)
gst_v4l2src_clear_format_list (v4l2src);
}
- if (((GObjectClass *) parent_class)->dispose)
- ((GObjectClass *) parent_class)->dispose (object);
+ G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -349,24 +345,19 @@ gst_v4l2src_set_property (GObject * object,
g_return_if_fail (GST_IS_V4L2SRC (object));
v4l2src = GST_V4L2SRC (object);
-
if (!gst_v4l2_object_set_property_helper (v4l2src->v4l2object,
prop_id, value, pspec)) {
-
switch (prop_id) {
case PROP_USE_FIXED_FPS:
if (!GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
v4l2src->use_fixed_fps = g_value_get_boolean (value);
}
break;
-
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
-
}
-
}
@@ -381,18 +372,15 @@ gst_v4l2src_get_property (GObject * object,
if (!gst_v4l2_object_get_property_helper (v4l2src->v4l2object,
prop_id, value, pspec)) {
-
switch (prop_id) {
case PROP_USE_FIXED_FPS:
g_value_set_boolean (value, v4l2src->use_fixed_fps);
break;
-
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
-
}
@@ -412,6 +400,8 @@ gst_v4l2src_fixate (GstPad * pad, GstCaps * caps)
structure = gst_caps_get_structure (caps, i);
const GValue *v;
+ /* FIXME such sizes? we usually fixate to something in the 320x200
+ * range... */
gst_structure_fixate_field_nearest_int (structure, "width", 4096);
gst_structure_fixate_field_nearest_int (structure, "height", 4096);
gst_structure_fixate_field_nearest_fraction (structure, "framerate", 15, 2);
@@ -755,7 +745,7 @@ gst_v4l2src_get_caps (GstBaseSrc * src)
&min_w, &max_w, &min_h, &max_h)) {
continue;
}
- /* template */
+ /* template, FIXME, why limit if the device reported correct results. */
min_w = CLAMP (min_w, 1, 4096);
min_h = CLAMP (min_h, 1, 4096);
max_w = CLAMP (max_w, min_w, 4096);
@@ -769,11 +759,11 @@ gst_v4l2src_get_caps (GstBaseSrc * src)
"width", GST_TYPE_INT_RANGE, min_w, max_w,
"height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
+ /* FIXME, why random range? */
gst_structure_set (structure, "framerate", GST_TYPE_FRACTION_RANGE,
1, 1, 100, 1, NULL);
gst_caps_append_structure (caps, structure);
-
}
}
@@ -860,14 +850,13 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
"framerate", GST_TYPE_FRACTION, v4l2src->fps_n, v4l2src->fps_d, NULL);
}
}
-
return TRUE;
}
/* start and stop are not symmetric -- start will open the device, but not start
- capture. it's setcaps that will start capture, which is called via basesrc's
- negotiate method. stop will both stop capture and close the device.
-*/
+ * capture. it's setcaps that will start capture, which is called via basesrc's
+ * negotiate method. stop will both stop capture and close the device.
+ */
static gboolean
gst_v4l2src_start (GstBaseSrc * src)
{
@@ -920,37 +909,42 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
} else if (amount == -1) {
if (errno == EAGAIN || errno == EINTR) {
continue;
- } else {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC,
- (_("error read()ing %d bytes on device %s"),
- buffersize, v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
- gst_buffer_unref (*buf);
- return GST_FLOW_ERROR;
- }
- } else {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
- ("error read()ing a buffer on device %s: got only %d bytes instead of expected %d",
- v4l2src->v4l2object->videodev, amount, buffersize));
- gst_buffer_unref (*buf);
- return GST_FLOW_ERROR;
- }
+ } else
+ goto read_error;
+ } else
+ goto short_read;
} while (TRUE);
return GST_FLOW_OK;
+ /* ERRORS */
+read_error:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC,
+ (_("error read()ing %d bytes on device %s"),
+ buffersize, v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
+ gst_buffer_unref (*buf);
+ return GST_FLOW_ERROR;
+ }
+short_read:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
+ ("error read()ing a buffer on device %s: got only %d bytes instead of expected %d",
+ v4l2src->v4l2object->videodev, amount, buffersize));
+ gst_buffer_unref (*buf);
+ return GST_FLOW_ERROR;
+ }
}
-
static GstFlowReturn
gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf)
{
- gint i, num = -1;
+ gint i, num;
-
- /* grab a frame from the device */
+ /* grab a frame from the device, post an error */
num = gst_v4l2src_grab_frame (v4l2src);
if (num == -1)
- return GST_FLOW_ERROR;
+ goto grab_failed;
i = v4l2src->format.fmt.pix.sizeimage;
@@ -958,23 +952,37 @@ gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf)
to avoid framedrops and deadlocks because of stupid elements */
if (g_atomic_int_get (&v4l2src->pool->refcount) == v4l2src->breq.count) {
GST_LOG_OBJECT (v4l2src, "using memcpy'd buffer");
+
*buf = gst_v4l2src_buffer_new (v4l2src, i, NULL, NULL);
memcpy (GST_BUFFER_DATA (*buf), v4l2src->pool->buffers[num].start, i);
- if (!gst_v4l2src_queue_frame (v4l2src, num)) {
- gst_buffer_unref (*buf);
- return GST_FLOW_ERROR;
- }
+
+ /* posts an error message if something went wrong */
+ if (!gst_v4l2src_queue_frame (v4l2src, num))
+ goto queue_failed;
} else {
GST_LOG_OBJECT (v4l2src, "using mmap'd buffer");
*buf =
gst_v4l2src_buffer_new (v4l2src, i, v4l2src->pool->buffers[num].start,
&v4l2src->pool->buffers[num]);
+
/* no need to be careful here, both are > 0, because the element uses them */
g_atomic_int_inc (&v4l2src->pool->buffers[num].refcount);
g_atomic_int_inc (&v4l2src->pool->refcount);
}
-
return GST_FLOW_OK;
+
+ /* ERRORS */
+grab_failed:
+ {
+ GST_DEBUG_OBJECT (v4l2src, "failed to grab a frame");
+ return GST_FLOW_ERROR;
+ }
+queue_failed:
+ {
+ GST_DEBUG_OBJECT (v4l2src, "failed to queue frame");
+ gst_buffer_unref (*buf);
+ return GST_FLOW_ERROR;
+ }
}
static GstFlowReturn
@@ -983,17 +991,22 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
GstV4l2Src *v4l2src = GST_V4L2SRC (src);
GstFlowReturn ret;
- if (v4l2src->use_fixed_fps && v4l2src->fps_n == 0) {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS,
- (_("could not get frame rate for %s, try to set use-fixed-fps property to false"), v4l2src->v4l2object->videodev), (NULL));
- return GST_FLOW_ERROR;
- }
+ if (v4l2src->use_fixed_fps && v4l2src->fps_n == 0)
+ goto no_framerate;
if (v4l2src->breq.memory == V4L2_MEMORY_MMAP) {
ret = gst_v4l2src_get_mmap (v4l2src, buf);
} else {
ret = gst_v4l2src_get_read (v4l2src, buf);
}
-
return ret;
+
+ /* ERRORS */
+no_framerate:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS,
+ (_("could not get frame rate for %s, try to set use-fixed-fps "
+ "property to false"), v4l2src->v4l2object->videodev), (NULL));
+ return GST_FLOW_ERROR;
+ }
}
diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c
index ba93e6e5..1d287d17 100644
--- a/sys/v4l2/v4l2_calls.c
+++ b/sys/v4l2/v4l2_calls.c
@@ -48,23 +48,28 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
* get the device's capturing capabilities
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2_get_capabilities (GstV4l2Object * v4l2object)
{
GST_DEBUG_OBJECT (v4l2object->element, "getting capabilities");
+
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &(v4l2object->vcap)) < 0) {
+ if (ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &v4l2object->vcap) < 0)
+ goto cap_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+cap_failed:
+ {
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
(_("Error getting capabilities for device '%s':"
" It isn't a v4l2 driver. Check if it is a v4l1 driver"),
v4l2object->videodev), GST_ERROR_SYSTEM);
return FALSE;
}
-
- return TRUE;
}
@@ -73,7 +78,6 @@ gst_v4l2_get_capabilities (GstV4l2Object * v4l2object)
* fill/empty the lists of enumerations
* return value: TRUE on success, FALSE on error
******************************************************/
-
static gboolean
gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
{
@@ -354,7 +358,6 @@ gst_v4l2_empty_lists (GstV4l2Object * v4l2object)
* open the video device (v4l2object->videodev)
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2_open (GstV4l2Object * v4l2object)
{
@@ -362,6 +365,7 @@ gst_v4l2_open (GstV4l2Object * v4l2object)
GST_DEBUG_OBJECT (v4l2object->element, "Trying to open device %s",
v4l2object->videodev);
+
GST_V4L2_CHECK_NOT_OPEN (v4l2object);
GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
@@ -370,65 +374,80 @@ gst_v4l2_open (GstV4l2Object * v4l2object)
v4l2object->videodev = g_strdup ("/dev/video");
/* check if it is a device */
- if (-1 == stat (v4l2object->videodev, &st)) {
+ if (stat (v4l2object->videodev, &st) == -1)
+ goto stat_failed;
+
+ if (!S_ISCHR (st.st_mode))
+ goto no_device;
+
+ /* open the device */
+ v4l2object->video_fd =
+ open (v4l2object->videodev, O_RDWR /* | O_NONBLOCK */ );
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ goto not_open;
+
+ /* get capabilities, error will be posted */
+ if (!gst_v4l2_get_capabilities (v4l2object))
+ goto error;
+
+ /* do we need to be a capture device? */
+ if (GST_IS_V4L2SRC (v4l2object) &&
+ !(v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
+ goto not_capture;
+
+ /* create enumerations, posts errors. */
+ if (!gst_v4l2_fill_lists (v4l2object))
+ goto error;
+
+ GST_INFO_OBJECT (v4l2object->element,
+ "Opened device '%s' (%s) successfully",
+ v4l2object->vcap.card, v4l2object->videodev);
+
+ return TRUE;
+
+ /* ERRORS */
+stat_failed:
+ {
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
(_("Cannot identify device '%s'"), v4l2object->videodev),
GST_ERROR_SYSTEM);
goto error;
}
- if (!S_ISCHR (st.st_mode)) {
+no_device:
+ {
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
(_("This isn't a device '%s'"), v4l2object->videodev),
GST_ERROR_SYSTEM);
goto error;
}
-
- /* open the device */
- v4l2object->video_fd =
- open (v4l2object->videodev, O_RDWR /* | O_NONBLOCK */ );
-
- if (!GST_V4L2_IS_OPEN (v4l2object)) {
+not_open:
+ {
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, OPEN_READ_WRITE,
(_("Could not open device \"%s\" for reading and writing."),
v4l2object->videodev), GST_ERROR_SYSTEM);
goto error;
}
-
- /* get capabilities */
- if (!gst_v4l2_get_capabilities (v4l2object)) {
- goto error;
- }
-
- /* do we need to be a capture device? */
- if (GST_IS_V4L2SRC (v4l2object) &&
- !(v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
+not_capture:
+ {
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
(_("Device \"%s\" is not a capture device."),
v4l2object->videodev),
("Capabilities: 0x%x", v4l2object->vcap.capabilities));
goto error;
}
-
- /* create enumerations */
- if (!gst_v4l2_fill_lists (v4l2object))
- goto error;
-
- GST_INFO_OBJECT (v4l2object->element,
- "Opened device '%s' (%s) successfully",
- v4l2object->vcap.card, v4l2object->videodev);
-
- return TRUE;
-
error:
- if (GST_V4L2_IS_OPEN (v4l2object)) {
- /* close device */
- close (v4l2object->video_fd);
- v4l2object->video_fd = -1;
- }
- /* empty lists */
- gst_v4l2_empty_lists (v4l2object);
+ {
+ if (GST_V4L2_IS_OPEN (v4l2object)) {
+ /* close device */
+ close (v4l2object->video_fd);
+ v4l2object->video_fd = -1;
+ }
+ /* empty lists */
+ gst_v4l2_empty_lists (v4l2object);
- return FALSE;
+ return FALSE;
+ }
}
@@ -437,12 +456,12 @@ error:
* close the video device (v4l2object->video_fd)
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2_close (GstV4l2Object * v4l2object)
{
GST_DEBUG_OBJECT (v4l2object->element, "Trying to close %s",
v4l2object->videodev);
+
GST_V4L2_CHECK_OPEN (v4l2object);
GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
@@ -462,24 +481,27 @@ gst_v4l2_close (GstV4l2Object * v4l2object)
* Get the norm of the current device
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2_get_norm (GstV4l2Object * v4l2object, v4l2_std_id * norm)
{
GST_DEBUG_OBJECT (v4l2object->element, "getting norm");
+
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (ioctl (v4l2object->video_fd, VIDIOC_G_STD, norm) < 0) {
+ if (ioctl (v4l2object->video_fd, VIDIOC_G_STD, norm) < 0)
+ goto std_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+std_failed:
+ {
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
(_("Failed to get the current norm for device %s"),
v4l2object->videodev), GST_ERROR_SYSTEM);
return FALSE;
}
-
-
-
- return TRUE;
}
@@ -488,22 +510,27 @@ gst_v4l2_get_norm (GstV4l2Object * v4l2object, v4l2_std_id * norm)
* Set the norm of the current device
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2_set_norm (GstV4l2Object * v4l2object, v4l2_std_id norm)
{
GST_DEBUG_OBJECT (v4l2object->element, "trying to set norm to %llx", norm);
+
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (ioctl (v4l2object->video_fd, VIDIOC_S_STD, &norm) < 0) {
+ if (ioctl (v4l2object->video_fd, VIDIOC_S_STD, &norm) < 0)
+ goto std_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+std_failed:
+ {
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
(_("Failed to set norm 0x%llx for device %s: %s"),
norm, v4l2object->videodev), GST_ERROR_SYSTEM);
return FALSE;
}
-
- return TRUE;
}
/******************************************************
@@ -511,7 +538,6 @@ gst_v4l2_set_norm (GstV4l2Object * v4l2object, v4l2_std_id norm)
* get the current frequency
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2_get_frequency (GstV4l2Object * v4l2object,
gint tunernum, gulong * frequency)
@@ -520,22 +546,28 @@ gst_v4l2_get_frequency (GstV4l2Object * v4l2object,
GstTunerChannel *channel;
GST_DEBUG_OBJECT (v4l2object->element, "getting current tuner frequency");
+
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
channel = gst_tuner_get_channel (GST_TUNER (v4l2object->element));
freq.tuner = tunernum;
- if (ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
+ if (ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0)
+ goto freq_failed;
+
+ *frequency = freq.frequency * channel->freq_multiplicator;
+
+ return TRUE;
+
+ /* ERRORS */
+freq_failed:
+ {
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
(_("Failed to get current tuner frequency for device %s"),
v4l2object->videodev), GST_ERROR_SYSTEM);
return FALSE;
}
-
- *frequency = freq.frequency * channel->freq_multiplicator;
-
- return TRUE;
}
@@ -544,7 +576,6 @@ gst_v4l2_get_frequency (GstV4l2Object * v4l2object,
* set frequency
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2_set_frequency (GstV4l2Object * v4l2object,
gint tunernum, gulong frequency)
@@ -554,6 +585,7 @@ gst_v4l2_set_frequency (GstV4l2Object * v4l2object,
GST_DEBUG_OBJECT (v4l2object->element,
"setting current tuner frequency to %lu", frequency);
+
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
@@ -564,23 +596,26 @@ gst_v4l2_set_frequency (GstV4l2Object * v4l2object,
ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq);
freq.frequency = frequency / channel->freq_multiplicator;
- if (ioctl (v4l2object->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0) {
+ if (ioctl (v4l2object->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0)
+ goto freq_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+freq_failed:
+ {
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
(_("Failed to set current tuner frequency for device %s to %lu"),
v4l2object->videodev, frequency), GST_ERROR_SYSTEM);
return FALSE;
}
-
- return TRUE;
}
-
/******************************************************
* gst_v4l2_signal_strength():
* get the strength of the signal on the current input
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2_signal_strength (GstV4l2Object * v4l2object,
gint tunernum, gulong * signal_strength)
@@ -588,53 +623,62 @@ gst_v4l2_signal_strength (GstV4l2Object * v4l2object,
struct v4l2_tuner tuner;
GST_DEBUG_OBJECT (v4l2object->element, "trying to get signal strength");
+
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
tuner.index = tunernum;
- if (ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &tuner) < 0) {
+ if (ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &tuner) < 0)
+ goto tuner_failed;
+
+ *signal_strength = tuner.signal;
+
+ return TRUE;
+
+ /* ERRORS */
+tuner_failed:
+ {
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
(_("Failed to get signal strength for device %s"),
v4l2object->videodev), GST_ERROR_SYSTEM);
return FALSE;
}
-
- *signal_strength = tuner.signal;
-
- return TRUE;
}
-
/******************************************************
* gst_v4l2_get_attribute():
* try to get the value of one specific attribute
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2_get_attribute (GstV4l2Object * v4l2object,
int attribute_num, int *value)
{
struct v4l2_control control;
- if (!GST_V4L2_IS_OPEN (v4l2object))
- return FALSE;
-
GST_DEBUG_OBJECT (v4l2object->element, "getting value of attribute %d",
attribute_num);
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
control.id = attribute_num;
- if (ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ if (ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
+ goto ctrl_failed;
+
+ *value = control.value;
+
+ return TRUE;
+
+ /* ERRORS */
+ctrl_failed:
+ {
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
(_("Failed to get value for control %d on device %s"),
attribute_num, v4l2object->videodev), GST_ERROR_SYSTEM);
return FALSE;
}
-
- *value = control.value;
-
- return TRUE;
}
@@ -643,30 +687,33 @@ gst_v4l2_get_attribute (GstV4l2Object * v4l2object,
* try to set the value of one specific attribute
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2_set_attribute (GstV4l2Object * v4l2object,
int attribute_num, const int value)
{
struct v4l2_control control;
- if (!GST_V4L2_IS_OPEN (v4l2object))
- return FALSE;
-
GST_DEBUG_OBJECT (v4l2object->element, "setting value of attribute %d to %d",
attribute_num, value);
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
control.id = attribute_num;
control.value = value;
+ if (ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0)
+ goto ctrl_failed;
+
+ return TRUE;
- if (ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ /* ERRORS */
+ctrl_failed:
+ {
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
(_("Failed to set value %d for control %d on device %s"),
value, attribute_num, v4l2object->videodev), GST_ERROR_SYSTEM);
return FALSE;
}
-
- return TRUE;
}
gboolean
@@ -675,36 +722,48 @@ gst_v4l2_get_input (GstV4l2Object * v4l2object, gint * input)
gint n;
GST_DEBUG_OBJECT (v4l2object->element, "trying to get input");
+
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (ioctl (v4l2object->video_fd, VIDIOC_G_INPUT, &n) < 0) {
+ if (ioctl (v4l2object->video_fd, VIDIOC_G_INPUT, &n) < 0)
+ goto input_failed;
+
+ *input = n;
+
+ return TRUE;
+
+ /* ERRORS */
+input_failed:
+ {
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
(_("Failed to get current input on device %s"),
v4l2object->videodev), GST_ERROR_SYSTEM);
return FALSE;
}
-
- *input = n;
-
- return TRUE;
}
gboolean
gst_v4l2_set_input (GstV4l2Object * v4l2object, gint input)
{
GST_DEBUG_OBJECT (v4l2object->element, "trying to set input to %d", input);
+
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (ioctl (v4l2object->video_fd, VIDIOC_S_INPUT, &input) < 0) {
+ if (ioctl (v4l2object->video_fd, VIDIOC_S_INPUT, &input) < 0)
+ goto input_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+input_failed:
+ {
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
(_("Failed to set input %d on device %s"),
input, v4l2object->videodev), GST_ERROR_SYSTEM);
return FALSE;
}
-
- return TRUE;
}
diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c
index 7e6e09e7..21b07f5c 100644
--- a/sys/v4l2/v4l2src_calls.c
+++ b/sys/v4l2/v4l2src_calls.c
@@ -53,7 +53,7 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
/* On some systems MAP_FAILED seems to be missing */
#ifndef MAP_FAILED
-#define MAP_FAILED ( (caddr_t) -1 )
+#define MAP_FAILED ((caddr_t) -1)
#endif
/******************************************************
@@ -61,7 +61,6 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
* create list of supported capture formats
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2src_fill_format_list (GstV4l2Src * v4l2src)
{
@@ -79,29 +78,32 @@ gst_v4l2src_fill_format_list (GstV4l2Src * v4l2src)
if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
if (errno == EINVAL) {
break; /* end of enumeration */
- } else {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS,
- (_("failed to get number %d in pixelformat enumeration for %s: %s"),
- n, v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
- g_free (format);
- return FALSE;
- }
+ } else
+ goto failed;
}
GST_LOG_OBJECT (v4l2src, "got format %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (format->pixelformat));
+
v4l2src->formats = g_slist_prepend (v4l2src->formats, format);
}
-
return TRUE;
-}
+ /* ERRORS */
+failed:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS,
+ (_("failed to get number %d in pixelformat enumeration for %s: %s"),
+ n, v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
+ g_free (format);
+ return FALSE;
+ }
+}
/******************************************************
* gst_v4l2src_clear_format_list():
* free list of supported capture formats
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2src_clear_format_list (GstV4l2Src * v4l2src)
{
@@ -118,14 +120,20 @@ gst_v4l2src_clear_format_list (GstV4l2Src * v4l2src)
* queue a frame for capturing
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2src_queue_frame (GstV4l2Src * v4l2src, guint i)
{
GST_LOG_OBJECT (v4l2src, "queueing frame %u", i);
if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_QBUF,
- &v4l2src->pool->buffers[i].buffer) < 0) {
+ &v4l2src->pool->buffers[i].buffer) < 0)
+ goto failed;
+
+ return TRUE;
+
+ /* ERRORS */
+failed:
+ {
GST_ELEMENT_ERROR (v4l2src, RESOURCE, WRITE,
(_("Could not write to device '%s'."),
v4l2src->v4l2object->videodev),
@@ -133,17 +141,13 @@ gst_v4l2src_queue_frame (GstV4l2Src * v4l2src, guint i)
v4l2src->v4l2object->videodev, g_strerror (errno)));
return FALSE;
}
-
- return TRUE;
}
-
/******************************************************
* gst_v4l2src_grab_frame ():
* grab a frame for capturing
- * return value: TRUE on success, FALSE on error
+ * return value: The captured frame number or -1 on error.
******************************************************/
-
gint
gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
{
@@ -163,17 +167,9 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
v4l2src->v4l2object->videodev);
break;
case EINVAL:
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED,
- (_("Failed trying to get frames from device %s"),
- v4l2src->v4l2object->videodev),
- (_("The buffer type is not supported, or the index is out of bounds," " or no buffers have been allocated yet, or the userptr" " or length are invalid. device %s"), v4l2src->v4l2object->videodev));
- break;
+ goto einval;
case ENOMEM:
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED,
- (_("Failed trying to get frames from device %s. Not enough memory"),
- v4l2src->v4l2object->videodev),
- (_("isufficient memory to enqueue a user pointer buffer. device %s"), v4l2src->v4l2object->videodev));
- break;
+ goto nomem;
case EIO:
GST_DEBUG_OBJECT (v4l2src,
"VIDIOC_DQBUF failed due to an internal error."
@@ -195,19 +191,49 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
}
if (--trials == -1) {
- return -1;
+ goto too_many_trials;
} else {
ioctl (v4l2src->v4l2object->video_fd, VIDIOC_QBUF, &buffer);
memset (&buffer, 0x00, sizeof (buffer));
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buffer.memory = v4l2src->breq.memory;
}
-
}
GST_LOG_OBJECT (v4l2src, "grabbed frame %d", buffer.index);
return buffer.index;
+
+ /* ERRORS */
+einval:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED,
+ (_("Failed trying to get frames from device %s"),
+ v4l2src->v4l2object->videodev),
+ (_("The buffer type is not supported, or the index is out of bounds,"
+ " or no buffers have been allocated yet, or the userptr"
+ " or length are invalid. device %s"),
+ v4l2src->v4l2object->videodev));
+ return -1;
+ }
+nomem:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED,
+ (_("Failed trying to get frames from device %s. Not enough memory"),
+ v4l2src->v4l2object->videodev),
+ (_("insufficient memory to enqueue a user pointer buffer. device %s"),
+ v4l2src->v4l2object->videodev));
+ return -1;
+ }
+too_many_trials:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED,
+ (_("Failed trying to get frames from device %s"),
+ v4l2src->v4l2object->videodev),
+ (_("Failed after 100 tries. device %s"),
+ v4l2src->v4l2object->videodev));
+ return -1;
+ }
}
@@ -216,7 +242,6 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
* get capture parameters
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2src_get_capture (GstV4l2Src * v4l2src)
{
@@ -226,14 +251,20 @@ gst_v4l2src_get_capture (GstV4l2Src * v4l2src)
memset (&v4l2src->format, 0, sizeof (struct v4l2_format));
v4l2src->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_FMT, &v4l2src->format) < 0) {
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_FMT, &v4l2src->format) < 0)
+ goto fmt_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+fmt_failed:
+ {
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS,
(_("failed to get pixelformat for device %s"),
v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
return FALSE;
}
-
- return TRUE;
}
@@ -242,13 +273,11 @@ gst_v4l2src_get_capture (GstV4l2Src * v4l2src)
* set capture parameters
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2src_set_capture (GstV4l2Src * v4l2src,
struct v4l2_fmtdesc * fmt, gint * width, gint * height,
guint * fps_n, guint * fps_d)
{
-
guint new_fps_n = *fps_n;
guint new_fps_d = *fps_d;
@@ -258,9 +287,9 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src,
GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
GST_V4L2_CHECK_NOT_ACTIVE (v4l2src->v4l2object);
- if (!gst_v4l2src_get_capture (v4l2src)) {
+ /* error was posted */
+ if (!gst_v4l2src_get_capture (v4l2src))
goto fail;
- }
v4l2src->format.fmt.pix.width = *width;
v4l2src->format.fmt.pix.height = *height;
@@ -268,13 +297,8 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src,
v4l2src->format.fmt.pix.field = V4L2_FIELD_INTERLACED;
v4l2src->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_FMT, &v4l2src->format) < 0) {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS,
- (_("failed to set pixelformat to %s @ %dx%d for device %s: %s"),
- fmt->description, *width, *height, v4l2src->v4l2object->videodev),
- GST_ERROR_SYSTEM);
- goto fail;
- }
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_FMT, &v4l2src->format) < 0)
+ goto fmt_failed;
if (*width != v4l2src->format.fmt.pix.width ||
*height != v4l2src->format.fmt.pix.height) {
@@ -283,18 +307,12 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src,
v4l2src->format.fmt.pix.height, fmt->description);
}
- /* update internal info */
- if (!gst_v4l2src_get_capture (v4l2src)) {
+ /* update internal info, posted error */
+ if (!gst_v4l2src_get_capture (v4l2src))
goto fail;
- }
- if (fmt->pixelformat != v4l2src->format.fmt.pix.pixelformat) {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS,
- (_("failed to set pixelformat to %s @ %dx%d for device %s: %s"),
- fmt->description, *width, *height, v4l2src->v4l2object->videodev),
- GST_ERROR_SYSTEM);
- goto fail;
- }
+ if (fmt->pixelformat != v4l2src->format.fmt.pix.pixelformat)
+ goto pixfmt_failed;
if (*fps_n) {
if (gst_v4l2src_set_fps (v4l2src, &new_fps_n, &new_fps_d)) {
@@ -313,30 +331,45 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src,
}
}
-
*width = v4l2src->format.fmt.pix.width;
*height = v4l2src->format.fmt.pix.height;
return TRUE;
+ /* ERRORS */
+fmt_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS,
+ (_("failed to set pixelformat to %s @ %dx%d for device %s: %s"),
+ fmt->description, *width, *height, v4l2src->v4l2object->videodev),
+ GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+pixfmt_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS,
+ (_("failed to set pixelformat to %s @ %dx%d for device %s: %s"),
+ fmt->description, *width, *height, v4l2src->v4l2object->videodev),
+ GST_ERROR_SYSTEM);
+ return FALSE;
+ }
fail:
-
- return FALSE;
-
+ {
+ return FALSE;
+ }
}
-
/******************************************************
* gst_v4l2src_capture_init():
* initialize the capture system
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
{
gint n;
guint buffers;
+ GstV4l2Buffer *buffer;
GST_DEBUG_OBJECT (v4l2src, "initting the capture system");
@@ -345,36 +378,25 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
/* request buffer info */
buffers = v4l2src->breq.count;
- if (v4l2src->breq.count > GST_V4L2_MAX_BUFFERS) {
+
+ if (v4l2src->breq.count > GST_V4L2_MAX_BUFFERS)
v4l2src->breq.count = GST_V4L2_MAX_BUFFERS;
- }
- if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS) {
+ else if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS)
v4l2src->breq.count = GST_V4L2_MIN_BUFFERS;
- }
+
v4l2src->breq.type = v4l2src->format.type;
if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
v4l2src->breq.memory = V4L2_MEMORY_MMAP;
if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_REQBUFS,
- &v4l2src->breq) < 0) {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
- (_("Could not get buffers from device '%s'."),
- v4l2src->v4l2object->videodev),
- ("error requesting %d buffers. system error: %s",
- v4l2src->breq.count, g_strerror (errno)));
- return FALSE;
- }
+ &v4l2src->breq) < 0)
+ goto reqbufs_failed;
+
GST_LOG_OBJECT (v4l2src, "using default mmap method");
} else if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_READWRITE) {
v4l2src->breq.memory = 0;
GST_INFO_OBJECT (v4l2src, "using fallback read method");
- } else {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
- (_("the driver of device '%s' is broken."),
- v4l2src->v4l2object->videodev),
- ("no supported read capability from %s",
- v4l2src->v4l2object->videodev));
- return FALSE;
- }
+ } else
+ goto broken_driver;
/* Determine the device's framerate */
if (!gst_v4l2src_update_fps (v4l2src->v4l2object)) {
@@ -384,15 +406,9 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
}
if (v4l2src->breq.memory > 0) {
- if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS) {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
- (_("Could not get enough buffers from device '%s'."),
- v4l2src->v4l2object->videodev),
- ("we received %d, we want at least %d",
- v4l2src->breq.count, GST_V4L2_MIN_BUFFERS));
- v4l2src->breq.count = buffers;
- return FALSE;
- }
+ if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS)
+ goto no_buffers;
+
if (v4l2src->breq.count != buffers)
g_object_notify (G_OBJECT (v4l2src), "num_buffers");
@@ -412,7 +428,7 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
v4l2src->pool->buffers = g_new0 (GstV4l2Buffer, v4l2src->breq.count);
for (n = 0; n < v4l2src->breq.count; n++) {
- GstV4l2Buffer *buffer = &v4l2src->pool->buffers[n];
+ buffer = &v4l2src->pool->buffers[n];
gst_atomic_int_set (&buffer->refcount, 1);
buffer->pool = v4l2src->pool;
@@ -422,28 +438,19 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
buffer->buffer.memory = v4l2src->breq.memory;
if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_QUERYBUF,
- &buffer->buffer) < 0) {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
- (_("Could not get buffer properties of buffer %d"), n),
- GST_ERROR_SYSTEM);
- gst_v4l2src_capture_deinit (v4l2src);
- return FALSE;
- }
+ &buffer->buffer) < 0)
+ goto querybuf_failed;
+
buffer->start =
mmap (0, buffer->buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED,
v4l2src->v4l2object->video_fd, buffer->buffer.m.offset);
- if (buffer->start == MAP_FAILED) {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
- (_("Could not mmap video buffer %d: %s"), n), GST_ERROR_SYSTEM);
- buffer->start = 0;
- gst_v4l2src_capture_deinit (v4l2src);
- return FALSE;
- }
+
+ if (buffer->start == MAP_FAILED)
+ goto mmap_failed;
+
buffer->length = buffer->buffer.length;
- if (!gst_v4l2src_queue_frame (v4l2src, n)) {
- gst_v4l2src_capture_deinit (v4l2src);
- return FALSE;
- }
+ if (!gst_v4l2src_queue_frame (v4l2src, n))
+ goto queue_failed;
}
} else {
GST_LOG_OBJECT (v4l2src, "no buffer pool used");
@@ -453,6 +460,57 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
GST_V4L2_SET_ACTIVE (v4l2src->v4l2object);
return TRUE;
+
+ /* ERRORS */
+reqbufs_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("Could not get buffers from device '%s'."),
+ v4l2src->v4l2object->videodev),
+ ("error requesting %d buffers. system error: %s",
+ v4l2src->breq.count, g_strerror (errno)));
+ return FALSE;
+ }
+broken_driver:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("the driver of device '%s' is broken."),
+ v4l2src->v4l2object->videodev),
+ ("no supported read capability from %s",
+ v4l2src->v4l2object->videodev));
+ return FALSE;
+ }
+no_buffers:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("Could not get enough buffers from device '%s'."),
+ v4l2src->v4l2object->videodev),
+ ("we received %d, we want at least %d",
+ v4l2src->breq.count, GST_V4L2_MIN_BUFFERS));
+ v4l2src->breq.count = buffers;
+ return FALSE;
+ }
+querybuf_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("Could not get buffer properties of buffer %d"), n),
+ GST_ERROR_SYSTEM);
+ gst_v4l2src_capture_deinit (v4l2src);
+ return FALSE;
+ }
+mmap_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("Could not mmap video buffer %d: %s"), n), GST_ERROR_SYSTEM);
+ gst_v4l2src_capture_deinit (v4l2src);
+ buffer->start = 0;
+ return FALSE;
+ }
+queue_failed:
+ {
+ gst_v4l2src_capture_deinit (v4l2src);
+ return FALSE;
+ }
}
@@ -461,7 +519,6 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
* start streaming capture
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2src_capture_start (GstV4l2Src * v4l2src)
{
@@ -470,52 +527,49 @@ gst_v4l2src_capture_start (GstV4l2Src * v4l2src)
GST_DEBUG_OBJECT (v4l2src, "starting the capturing");
GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
- if (!GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
- /* gst_pad_renegotiate (v4l2src->srcpad); FIX: is it still required in 0.10 */
- }
GST_V4L2_CHECK_ACTIVE (v4l2src->v4l2object);
v4l2src->quit = FALSE;
if (v4l2src->breq.memory != 0) {
- if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_STREAMON, &type) < 0) {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, OPEN_READ,
- (_("Error starting streaming capture from device %s"),
- v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
- return FALSE;
- }
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_STREAMON, &type) < 0)
+ goto streamon_failed;
}
v4l2src->is_capturing = TRUE;
return TRUE;
-}
+ /* ERRORS */
+streamon_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, OPEN_READ,
+ (_("Error starting streaming capture from device %s"),
+ v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
/******************************************************
* gst_v4l2src_capture_stop():
* stop streaming capture
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2src_capture_stop (GstV4l2Src * v4l2src)
{
gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
GST_DEBUG_OBJECT (v4l2src, "stopping capturing");
+
GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
GST_V4L2_CHECK_ACTIVE (v4l2src->v4l2object);
if (v4l2src->breq.memory != 0) {
/* we actually need to sync on all queued buffers but not
* on the non-queued ones */
- if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_STREAMOFF, &type) < 0) {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, CLOSE,
- (_("Error stopping streaming capture from device %s: %s"),
- v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
- return FALSE;
- }
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_STREAMOFF, &type) < 0)
+ goto streamoff_failed;
}
/* make an optional pending wait stop */
@@ -523,6 +577,15 @@ gst_v4l2src_capture_stop (GstV4l2Src * v4l2src)
v4l2src->is_capturing = FALSE;
return TRUE;
+
+ /* ERRORS */
+streamoff_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, CLOSE,
+ (_("Error stopping streaming capture from device %s: %s"),
+ v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
}
static void
@@ -570,7 +633,6 @@ gst_v4l2src_free_buffer (GstBuffer * buffer)
* deinitialize the capture system
* return value: TRUE on success, FALSE on error
******************************************************/
-
gboolean
gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
{
@@ -608,20 +670,20 @@ gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
*/
if (try_reinit) {
if (!gst_v4l2src_capture_start (v4l2src) ||
- !gst_v4l2src_capture_stop (v4l2src))
+ !gst_v4l2src_capture_stop (v4l2src)) {
+ GST_DEBUG_OBJECT (v4l2src, "failed reinit device");
return FALSE;
+ }
}
}
GST_V4L2_SET_INACTIVE (v4l2src->v4l2object);
+
return TRUE;
}
-
/*
-
*/
-
gboolean
gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
struct v4l2_fmtdesc * format,
@@ -642,6 +704,8 @@ gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
fmt.fmt.pix.pixelformat = format->pixelformat;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_TRY_FMT, &fmt) < 0) {
+ GST_DEBUG_OBJECT (v4l2src, "failed to get min size: %s",
+ g_strerror (errno));
return FALSE;
}
@@ -649,12 +713,15 @@ gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
*min_w = fmt.fmt.pix.width;
if (min_h)
*min_h = fmt.fmt.pix.height;
+
GST_LOG_OBJECT (v4l2src,
"got min size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
fmt.fmt.pix.width = 4096;
fmt.fmt.pix.height = 4096;
if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_TRY_FMT, &fmt) < 0) {
+ GST_DEBUG_OBJECT (v4l2src, "failed to get max size: %s",
+ g_strerror (errno));
return FALSE;
}
@@ -662,6 +729,7 @@ gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
*max_w = fmt.fmt.pix.width;
if (max_h)
*max_h = fmt.fmt.pix.height;
+
GST_LOG_OBJECT (v4l2src,
"got max size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
@@ -680,29 +748,49 @@ gst_v4l2src_update_fps (GstV4l2Object * v4l2object)
gboolean
gst_v4l2src_set_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d)
{
-
GstV4l2Object *v4l2object = v4l2src->v4l2object;
struct v4l2_streamparm stream;
+ GST_LOG_OBJECT (v4l2src, "setting fps %d, %d", *fps_n, *fps_d);
+
memset (&stream, 0x00, sizeof (struct v4l2_streamparm));
stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (ioctl (v4l2object->video_fd, VIDIOC_G_PARM, &stream) == 0 &&
- stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
+ if (ioctl (v4l2object->video_fd, VIDIOC_G_PARM, &stream) < 0)
+ goto gparm_failed;
- stream.parm.capture.timeperframe.denominator = *fps_n;
- stream.parm.capture.timeperframe.numerator = *fps_d;
+ if (!(stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
+ goto no_timeperframe;
- if (ioctl (v4l2object->video_fd, VIDIOC_S_PARM, &stream) == 0) {
- *fps_n = stream.parm.capture.timeperframe.denominator;
- *fps_d = stream.parm.capture.timeperframe.numerator;
- return TRUE;
- }
- }
+ stream.parm.capture.timeperframe.denominator = *fps_n;
+ stream.parm.capture.timeperframe.numerator = *fps_d;
- return FALSE;
+ if (ioctl (v4l2object->video_fd, VIDIOC_S_PARM, &stream) < 0)
+ goto sparm_failed;
-}
+ *fps_n = stream.parm.capture.timeperframe.denominator;
+ *fps_d = stream.parm.capture.timeperframe.numerator;
+ GST_LOG_OBJECT (v4l2src, "fps set to %d, %d", *fps_n, *fps_d);
+
+ return TRUE;
+
+ /* ERRORS */
+gparm_failed:
+ {
+ GST_DEBUG_OBJECT (v4l2src, "failed to get PARM: %s", g_strerror (errno));
+ return FALSE;
+ }
+no_timeperframe:
+ {
+ GST_DEBUG_OBJECT (v4l2src, "no V4L2_CAP_TIMEPERFRAME");
+ return FALSE;
+ }
+sparm_failed:
+ {
+ GST_DEBUG_OBJECT (v4l2src, "failed to set PARM: %s", g_strerror (errno));
+ return FALSE;
+ }
+}
gboolean
gst_v4l2src_get_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d)
@@ -711,6 +799,7 @@ gst_v4l2src_get_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d)
v4l2_std_id std;
struct v4l2_streamparm stream;
const GList *item;
+ gboolean found;
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
@@ -718,36 +807,60 @@ gst_v4l2src_get_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d)
/* Try to get the frame rate directly from the device using VIDIOC_G_PARM */
memset (&stream, 0x00, sizeof (struct v4l2_streamparm));
stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (ioctl (v4l2object->video_fd, VIDIOC_G_PARM, &stream) == 0 &&
- stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
- /* Note: V4L2 gives us the frame interval, we need the frame rate */
- *fps_n = stream.parm.capture.timeperframe.denominator;
- *fps_d = stream.parm.capture.timeperframe.numerator;
- GST_DEBUG_OBJECT (v4l2src,
- "frame rate returned by G_PARM: %d/%d fps", *fps_n, *fps_d);
- return TRUE;
+
+ if (ioctl (v4l2object->video_fd, VIDIOC_G_PARM, &stream) < 0) {
+ GST_DEBUG_OBJECT (v4l2src, "failed to get PARM: %s", g_strerror (errno));
+ goto try_stds;
}
+ if (!(stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) {
+ GST_DEBUG_OBJECT (v4l2src, "no V4L2_CAP_TIMEPERFRAME");
+ goto try_stds;
+ }
+
+ /* Note: V4L2 gives us the frame interval, we need the frame rate */
+ *fps_n = stream.parm.capture.timeperframe.denominator;
+ *fps_d = stream.parm.capture.timeperframe.numerator;
+
+ GST_DEBUG_OBJECT (v4l2src,
+ "frame rate returned by G_PARM: %d/%d fps", *fps_n, *fps_d);
+ /* and we are done now */
+ goto done;
+
+try_stds:
/* If G_PARM failed, try to get the same information from the video standard */
if (!gst_v4l2_get_norm (v4l2object, &std))
return FALSE;
+
+ found = FALSE;
for (item = v4l2object->stds; item != NULL; item = item->next) {
GstV4l2TunerNorm *v4l2norm = item->data;
if (v4l2norm->index == std) {
- *fps_n =
- gst_value_get_fraction_numerator (&GST_TUNER_NORM (v4l2norm)->
- framerate);
- *fps_d =
- gst_value_get_fraction_denominator (&GST_TUNER_NORM (v4l2norm)->
- framerate);
+ GValue *framerate = &GST_TUNER_NORM (v4l2norm)->framerate;
+
+ *fps_n = gst_value_get_fraction_numerator (framerate);
+ *fps_d = gst_value_get_fraction_denominator (framerate);
+
GST_DEBUG_OBJECT (v4l2src,
"frame rate returned by get_norm: %d/%d fps", *fps_n, *fps_d);
- return TRUE;
+ found = TRUE;
+ break;
}
}
- return FALSE;
+ /* nothing found, that's an error */
+ if (!found)
+ goto failed;
+
+done:
+ return TRUE;
+ /* ERRORS */
+failed:
+ {
+ GST_DEBUG_OBJECT (v4l2src, "failed to get framerate");
+ return FALSE;
+ }
}
#define GST_TYPE_V4L2SRC_BUFFER (gst_v4l2src_buffer_get_type())
@@ -812,7 +925,6 @@ gst_v4l2src_buffer_finalize (GstV4l2SrcBuffer * v4l2src_buffer)
GstV4l2Buffer *buf = v4l2src_buffer->buf;
if (buf) {
-
GST_LOG ("freeing buffer %p (nr. %d)", buf, buf->buffer.index);
if (!g_atomic_int_dec_and_test (&buf->refcount)) {
@@ -825,7 +937,6 @@ gst_v4l2src_buffer_finalize (GstV4l2SrcBuffer * v4l2src_buffer)
/* we're last thing that used all this */
gst_v4l2src_buffer_pool_free (buf->pool, TRUE);
}
-
}
}
@@ -845,9 +956,6 @@ gst_v4l2src_buffer_new (GstV4l2Src * v4l2src, guint size, guint8 * data,
GST_LOG_OBJECT (v4l2src,
"creating buffer %p (nr. %d)", srcbuf, srcbuf->buffer.index);
}
-
-
-
GST_BUFFER_SIZE (buf) = size;
GST_BUFFER_TIMESTAMP (buf) =