diff options
Diffstat (limited to 'sys/v4l2')
-rw-r--r-- | sys/v4l2/gstv4l2colorbalance.c | 6 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2colorbalance.h | 2 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2element.c | 134 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2src.c | 24 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2src.h | 47 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2tuner.c | 14 | ||||
-rw-r--r-- | sys/v4l2/v4l2_calls.c | 48 | ||||
-rw-r--r-- | sys/v4l2/v4l2src_calls.c | 51 | ||||
-rw-r--r-- | sys/v4l2/v4l2src_calls.h | 52 |
9 files changed, 223 insertions, 155 deletions
diff --git a/sys/v4l2/gstv4l2colorbalance.c b/sys/v4l2/gstv4l2colorbalance.c index 9c2cfa2c..06805fcc 100644 --- a/sys/v4l2/gstv4l2colorbalance.c +++ b/sys/v4l2/gstv4l2colorbalance.c @@ -79,7 +79,7 @@ gst_v4l2_color_balance_channel_class_init (GstV4l2ColorBalanceChannelClass * static void gst_v4l2_color_balance_channel_init (GstV4l2ColorBalanceChannel * channel) { - channel->index = 0; + channel->id = (guint32) - 1; } void @@ -125,7 +125,7 @@ gst_v4l2_color_balance_set_value (GstColorBalance * balance, g_return_if_fail (gst_v4l2_color_balance_contains_channel (v4l2element, v4l2channel)); - gst_v4l2_set_attribute (v4l2element, v4l2channel->index, value); + gst_v4l2_set_attribute (v4l2element, v4l2channel->id, value); } static gint @@ -142,7 +142,7 @@ gst_v4l2_color_balance_get_value (GstColorBalance * balance, g_return_val_if_fail (gst_v4l2_color_balance_contains_channel (v4l2element, v4l2channel), 0); - if (!gst_v4l2_get_attribute (v4l2element, v4l2channel->index, &value)) + if (!gst_v4l2_get_attribute (v4l2element, v4l2channel->id, &value)) return 0; return value; diff --git a/sys/v4l2/gstv4l2colorbalance.h b/sys/v4l2/gstv4l2colorbalance.h index 487b3482..358270fc 100644 --- a/sys/v4l2/gstv4l2colorbalance.h +++ b/sys/v4l2/gstv4l2colorbalance.h @@ -44,7 +44,7 @@ G_BEGIN_DECLS typedef struct _GstV4l2ColorBalanceChannel { GstColorBalanceChannel parent; - guint32 index; + guint32 id; } GstV4l2ColorBalanceChannel; typedef struct _GstV4l2ColorBalanceChannelClass { diff --git a/sys/v4l2/gstv4l2element.c b/sys/v4l2/gstv4l2element.c index e5acbf87..d6f14d47 100644 --- a/sys/v4l2/gstv4l2element.c +++ b/sys/v4l2/gstv4l2element.c @@ -1,23 +1,17 @@ -/* GStreamer - * - * gstv4l2element.c: base class for V4L2 elements - * - * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net> - * - * 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. - * +/* + * GStreamer gstv4l2element.c: base class for V4L2 elements Copyright + * (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net> 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. + * 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 @@ -56,8 +50,6 @@ static void gst_v4l2element_init_interfaces (GType type); GST_BOILERPLATE_FULL (GstV4l2Element, gst_v4l2element, GstPushSrc, GST_TYPE_PUSH_SRC, gst_v4l2element_init_interfaces) - - static void gst_v4l2element_dispose (GObject * object); static void gst_v4l2element_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); @@ -95,7 +87,9 @@ GST_BOILERPLATE_FULL (GstV4l2Element, gst_v4l2element, GstPushSrc, static void gst_v4l2_interface_init (GstImplementsInterfaceClass * klass) { - /* default virtual functions */ + /* + * default virtual functions + */ klass->supported = gst_v4l2_iface_supported; } @@ -130,21 +124,32 @@ gst_v4l2_class_probe_devices (GstV4l2ElementClass * klass, gboolean check) g_free (device); } - /* detect /dev entries */ + /* + * detect /dev entries + */ for (n = 0; n < 64; n++) { for (base = 0; dev_base[base] != NULL; base++) { struct stat s; - gchar *device = g_strdup_printf ("%s%d", dev_base[base], n); + gchar *device = g_strdup_printf ("%s%d", + dev_base[base], + n); - /* does the /dev/ entry exist at all? */ + /* + * does the /dev/ entry exist at all? + */ if (stat (device, &s) == 0) { - /* yes: is a device attached? */ - if ((fd = open (device, O_RDONLY)) > 0 || errno == EBUSY) { - if (fd > 0) - close (fd); - - devices = g_list_append (devices, device); - break; + /* + * yes: is a device attached? + */ + if (S_ISCHR (s.st_mode)) { + + if ((fd = open (device, O_RDWR | O_NONBLOCK)) > 0 || errno == EBUSY) { + if (fd > 0) + close (fd); + + devices = g_list_append (devices, device); + break; + } } } g_free (device); @@ -256,12 +261,22 @@ gst_v4l2_device_get_type (void) if (v4l2_device_type == 0) { static const GFlagsValue values[] = { - {V4L2_CAP_VIDEO_CAPTURE, "CAPTURE", "Device can capture"}, - {V4L2_CAP_VIDEO_OUTPUT, "PLAYBACK", "Device can playback"}, - {V4L2_CAP_VIDEO_OVERLAY, "OVERLAY", "Device can do overlay"}, - - {V4L2_CAP_TUNER, "TUNER", "Device has a tuner"}, - {V4L2_CAP_AUDIO, "AUDIO", "Device handles audio"}, + {V4L2_CAP_VIDEO_CAPTURE, "CAPTURE", + "Device supports video capture"}, + {V4L2_CAP_VIDEO_OUTPUT, "PLAYBACK", + "Device supports video playback"}, + {V4L2_CAP_VIDEO_OVERLAY, "OVERLAY", + "Device supports video overlay"}, + + {V4L2_CAP_VBI_CAPTURE, "VBI_CAPTURE", + "Device supports the VBI capture"}, + {V4L2_CAP_VBI_OUTPUT, "VBI_OUTPUT", + "Device supports the VBI output"}, + + {V4L2_CAP_TUNER, "TUNER", + "Device has a tuner or modulator"}, + {V4L2_CAP_AUDIO, "AUDIO", + "Device has audio inputs or outputs"}, {0, NULL, NULL} }; @@ -312,8 +327,8 @@ gst_v4l2element_init_interfaces (GType type) #endif g_type_add_interface_static (type, GST_TYPE_COLOR_BALANCE, &v4l2_colorbalance_info); - g_type_add_interface_static (type, - GST_TYPE_PROPERTY_PROBE, &v4l2_propertyprobe_info); + g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE, + &v4l2_propertyprobe_info); } @@ -338,22 +353,26 @@ gst_v4l2element_class_init (GstV4l2ElementClass * klass) gobject_class->get_property = gst_v4l2element_get_property; g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE, - g_param_spec_string ("device", "Device", "Device location", - NULL, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE_NAME, - g_param_spec_string ("device_name", "Device name", "Name of the device", - NULL, G_PARAM_READABLE)); + g_param_spec_string ("device", + "Device", "Device location", NULL, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), + PROP_DEVICE_NAME, + g_param_spec_string ("device_name", + "Device name", "Name of the device", NULL, G_PARAM_READABLE)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FLAGS, - g_param_spec_flags ("flags", "Flags", "Device type flags", + g_param_spec_flags ("flags", "Flags", + "Device type flags", 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_object_class_install_property (gobject_class, PROP_INPUT, - g_param_spec_string ("input", "input", + g_param_spec_string ("input", + "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", + g_param_spec_ulong ("frequency", + "frequency", "frequency to tune to (in Hz)", 0, G_MAXULONG, 0, G_PARAM_READWRITE)); basesrc_class->start = gst_v4l2element_start; @@ -366,7 +385,9 @@ gst_v4l2element_class_init (GstV4l2ElementClass * klass) static void gst_v4l2element_init (GstV4l2Element * v4l2element, GstV4l2ElementClass * klass) { - /* some default values */ + /* + * some default values + */ v4l2element->video_fd = -1; v4l2element->buffer = NULL; v4l2element->videodev = g_strdup ("/dev/video0"); @@ -410,7 +431,8 @@ gst_v4l2element_set_property (GObject * object, if (GST_V4L2_IS_OPEN (v4l2element)) { GstTuner *tuner = GST_TUNER (v4l2element); GstTunerNorm *norm = gst_tuner_find_norm_by_name (tuner, - (gchar *) g_value_get_string (value)); + (gchar *) + g_value_get_string (value)); if (norm) { gst_tuner_set_norm (tuner, norm); @@ -425,7 +447,8 @@ gst_v4l2element_set_property (GObject * object, if (GST_V4L2_IS_OPEN (v4l2element)) { GstTuner *tuner = GST_TUNER (v4l2element); GstTunerChannel *channel = gst_tuner_find_channel_by_name (tuner, - (gchar *) g_value_get_string (value)); + (gchar *) + g_value_get_string (value)); if (channel) { gst_tuner_set_channel (tuner, channel); @@ -467,7 +490,8 @@ gst_v4l2element_get_property (GObject * object, case PROP_DEVICE: g_value_set_string (value, v4l2element->videodev); break; - case PROP_DEVICE_NAME:{ + case PROP_DEVICE_NAME: + { gchar *new = NULL; if (GST_V4L2_IS_OPEN (v4l2element)) @@ -475,12 +499,14 @@ gst_v4l2element_get_property (GObject * object, g_value_set_string (value, new); break; } - case PROP_FLAGS:{ + case PROP_FLAGS: + { guint flags = 0; if (GST_V4L2_IS_OPEN (v4l2element)) { flags |= v4l2element->vcap.capabilities & - (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | + (V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_TUNER | V4L2_CAP_AUDIO); if (v4l2element->vcap.capabilities & V4L2_CAP_AUDIO) flags |= V4L2_FBUF_CAP_CHROMAKEY; diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index 2c331dd1..ee3c9841 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -115,9 +115,8 @@ static void gst_v4l2src_fixate (GstPad * pad, GstCaps * caps); static void gst_v4l2src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static void -gst_v4l2src_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_v4l2src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); static GstCaps *gst_v4l2src_get_all_caps (void); @@ -270,6 +269,7 @@ gst_v4l2src_fixate (GstPad * pad, GstCaps * caps) gst_structure_fixate_field_nearest_int (structure, "width", G_MAXINT); gst_structure_fixate_field_nearest_int (structure, "height", G_MAXINT); + gst_structure_fixate_field_nearest_fraction (structure, "framerate", 15, 2); v = gst_structure_get_value (structure, "format"); if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) { @@ -597,7 +597,10 @@ gst_v4l2src_get_caps (GstBaseSrc * src) /* build our own capslist */ caps = gst_caps_new_empty (); walk = v4l2src->formats; - gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d); + if (!gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d)) { + fps_n = 0; + fps_d = 1; + } while (walk) { format = (struct v4l2_fmtdesc *) walk->data; walk = g_slist_next (walk); @@ -619,10 +622,19 @@ gst_v4l2src_get_caps (GstBaseSrc * src) if (structure) { gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, min_w, max_w, - "height", GST_TYPE_INT_RANGE, min_h, max_h, - "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL); + "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL); + if (fps_n > 0) { + gst_structure_set (structure, "framerate", GST_TYPE_FRACTION, + fps_n, fps_d, NULL); + } gst_caps_append_structure (caps, structure); + + if (fps_n <= 0) { + gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION_RANGE, + 1, 1, 100, 1, NULL); + } + } } diff --git a/sys/v4l2/gstv4l2src.h b/sys/v4l2/gstv4l2src.h index 12c3cd44..3b3f96a6 100644 --- a/sys/v4l2/gstv4l2src.h +++ b/sys/v4l2/gstv4l2src.h @@ -32,7 +32,6 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug); #define GST_V4L2_MIN_BUFFERS 2 G_BEGIN_DECLS - #define GST_TYPE_V4L2SRC \ (gst_v4l2src_get_type()) #define GST_V4L2SRC(obj) \ @@ -43,37 +42,37 @@ G_BEGIN_DECLS (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2SRC)) #define GST_IS_V4L2SRC_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2SRC)) - - -typedef struct _GstV4l2BufferPool GstV4l2BufferPool; -typedef struct _GstV4l2Buffer GstV4l2Buffer; +typedef struct _GstV4l2BufferPool GstV4l2BufferPool; +typedef struct _GstV4l2Buffer GstV4l2Buffer; typedef struct _GstV4l2Src GstV4l2Src; typedef struct _GstV4l2SrcClass GstV4l2SrcClass; /* global info */ -struct _GstV4l2BufferPool { - gint refcount; /* number of users: 1 for every buffer, 1 for element */ - gint video_fd; - guint buffer_count; - GstV4l2Buffer * buffers; +struct _GstV4l2BufferPool +{ + gint refcount; /* number of users: 1 for every buffer, 1 for element */ + gint video_fd; + guint buffer_count; + GstV4l2Buffer *buffers; }; -struct _GstV4l2Buffer { - struct v4l2_buffer buffer; - guint8 * start; - guint length; - gint refcount; /* add 1 if in use by element, add 1 if in use by GstBuffer */ - GstV4l2BufferPool * pool; +struct _GstV4l2Buffer +{ + struct v4l2_buffer buffer; + guint8 *start; + guint length; + gint refcount; /* add 1 if in use by element, add 1 if in use by GstBuffer */ + GstV4l2BufferPool *pool; }; enum - { - QUEUE_STATE_ERROR = -1, - QUEUE_STATE_READY_FOR_QUEUE, /* the frame is ready to be queued for capture */ - QUEUE_STATE_QUEUED, /* the frame is queued for capture */ - QUEUE_STATE_SYNCED /* the frame is captured */ - }; +{ + QUEUE_STATE_ERROR = -1, + QUEUE_STATE_READY_FOR_QUEUE, /* the frame is ready to be queued for capture */ + QUEUE_STATE_QUEUED, /* the frame is queued for capture */ + QUEUE_STATE_SYNCED /* the frame is captured */ +}; struct _GstV4l2Src @@ -84,7 +83,7 @@ struct _GstV4l2Src GstPad *srcpad; /* internal lists */ - GSList *formats; /* list of available capture formats */ + GSList *formats; /* list of available capture formats */ /* buffers */ GstV4l2BufferPool *pool; @@ -111,6 +110,4 @@ GType gst_v4l2src_get_type (void); G_END_DECLS - - #endif /* __GST_V4L2SRC_H__ */ diff --git a/sys/v4l2/gstv4l2tuner.c b/sys/v4l2/gstv4l2tuner.c index 9fb4e3cd..add688c6 100644 --- a/sys/v4l2/gstv4l2tuner.c +++ b/sys/v4l2/gstv4l2tuner.c @@ -91,9 +91,9 @@ gst_v4l2_tuner_channel_class_init (GstV4l2TunerChannelClass * klass) static void gst_v4l2_tuner_channel_init (GstV4l2TunerChannel * channel) { - channel->index = 0; - channel->tuner = 0; - channel->audio = 0; + channel->index = (guint32) - 1; + channel->tuner = (guint32) - 1; + channel->audio = (guint32) - 1; } GType @@ -314,8 +314,8 @@ gst_v4l2_tuner_get_frequency (GstTuner * mixer, GstTunerChannel * channel) g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), 0); g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY), 0); - g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2element, - v4l2channel), 0); + g_return_val_if_fail (gst_v4l2_tuner_contains_channel + (v4l2element, v4l2channel), 0); gst_v4l2_get_input (v4l2element, &chan); if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index && @@ -338,8 +338,8 @@ gst_v4l2_tuner_signal_strength (GstTuner * mixer, GstTunerChannel * channel) g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), 0); g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY), 0); - g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2element, - v4l2channel), 0); + g_return_val_if_fail (gst_v4l2_tuner_contains_channel + (v4l2element, v4l2channel), 0); gst_v4l2_get_input (v4l2element, &chan); if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index && diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c index a89122f4..81516b41 100644 --- a/sys/v4l2/v4l2_calls.c +++ b/sys/v4l2/v4l2_calls.c @@ -252,7 +252,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element) v4l2channel = g_object_new (GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, NULL); channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel); channel->label = g_strdup ((const gchar *) control.name); - v4l2channel->index = n; + v4l2channel->id = n; #if 0 if (control.type == V4L2_CTRL_TYPE_MENU) { @@ -335,9 +335,11 @@ gst_v4l2_set_defaults (GstV4l2Element * v4l2element) gst_tuner_set_norm (tuner, norm); } else { norm = GST_TUNER_NORM (gst_tuner_get_norm (GST_TUNER (v4l2element))); - v4l2element->std = g_strdup (norm->label); - gst_tuner_norm_changed (tuner, norm); - g_object_notify (G_OBJECT (v4l2element), "std"); + if (norm) { + v4l2element->std = g_strdup (norm->label); + gst_tuner_norm_changed (tuner, norm); + g_object_notify (G_OBJECT (v4l2element), "std"); + } } if (v4l2element->input) @@ -377,6 +379,8 @@ gst_v4l2_set_defaults (GstV4l2Element * v4l2element) gboolean gst_v4l2_open (GstV4l2Element * v4l2element) { + struct stat st; + GST_DEBUG ("Trying to open device %s", v4l2element->videodev); GST_V4L2_CHECK_NOT_OPEN (v4l2element); GST_V4L2_CHECK_NOT_ACTIVE (v4l2element); @@ -385,8 +389,21 @@ gst_v4l2_open (GstV4l2Element * v4l2element) if (!v4l2element->videodev) v4l2element->videodev = g_strdup ("/dev/video"); + /* check if it is a device */ + if (-1 == stat (v4l2element->videodev, &st)) { + GST_ERROR ("Cannot identify '%s': %d, %s\n", + v4l2element->videodev, errno, strerror (errno)); + goto error; + } + if (!S_ISCHR (st.st_mode)) { + GST_ERROR ("%s is no device\n", v4l2element->videodev); + goto error; + } + /* open the device */ - v4l2element->video_fd = open (v4l2element->videodev, O_RDWR); + v4l2element->video_fd = open (v4l2element->videodev, + O_RDWR /* | O_NONBLOCK */ ); + if (!GST_V4L2_IS_OPEN (v4l2element)) { GST_ELEMENT_ERROR (v4l2element, RESOURCE, OPEN_READ_WRITE, (_("Could not open device \"%s\" for reading and writing."), @@ -403,8 +420,9 @@ gst_v4l2_open (GstV4l2Element * v4l2element) if (GST_IS_V4L2SRC (v4l2element) && !(v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { GST_ELEMENT_ERROR (v4l2element, RESOURCE, NOT_FOUND, - (_("Device \"%s\" is not a capture device."), v4l2element->videodev), - ("Capabilities: 0x%x", v4l2element->vcap.capabilities)); + (_("Device \"%s\" is not a capture device."), + v4l2element->videodev), ("Capabilities: 0x%x", + v4l2element->vcap.capabilities)); goto error; } @@ -524,8 +542,8 @@ gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input) if (ioctl (v4l2element->video_fd, VIDIOC_G_INPUT, &n) < 0) { GST_WARNING_OBJECT (v4l2element, - "Failed to get current input on device %s: %s", v4l2element->videodev, - g_strerror (errno)); + "Failed to get current input on device %s: %s", + v4l2element->videodev, g_strerror (errno)); return FALSE; } @@ -577,8 +595,8 @@ gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output) if (ioctl (v4l2element->video_fd, VIDIOC_G_OUTPUT, &n) < 0) { GST_WARNING_OBJECT (v4l2element, - "Failed to get current output on device %s: %s", v4l2element->videodev, - g_strerror (errno)); + "Failed to get current output on device %s: %s", + v4l2element->videodev, g_strerror (errno)); return FALSE; } @@ -735,8 +753,8 @@ gst_v4l2_get_attribute (GstV4l2Element * v4l2element, if (ioctl (v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) { GST_WARNING_OBJECT (v4l2element, - "Failed to get value for control %d on device %s: %s", attribute_num, - v4l2element->videodev, g_strerror (errno)); + "Failed to get value for control %d on device %s: %s", + attribute_num, v4l2element->videodev, g_strerror (errno)); return FALSE; } @@ -768,8 +786,8 @@ gst_v4l2_set_attribute (GstV4l2Element * v4l2element, if (ioctl (v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) { GST_WARNING_OBJECT (v4l2element, - "Failed to set value %d for control %d on device %s: %s", value, - attribute_num, v4l2element->videodev, g_strerror (errno)); + "Failed to set value %d for control %d on device %s: %s", + value, attribute_num, v4l2element->videodev, g_strerror (errno)); return FALSE; } diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c index 6dfe4494..73adb042 100644 --- a/sys/v4l2/v4l2src_calls.c +++ b/sys/v4l2/v4l2src_calls.c @@ -144,8 +144,11 @@ gint gst_v4l2src_grab_frame (GstV4l2Src * v4l2src) { struct v4l2_buffer buffer; + gint32 trials = 100; + memset (&buffer, 0x00, sizeof (buffer)); buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buffer.memory = v4l2src->breq.memory; while (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_DQBUF, &buffer) < 0) { /* if the sync() got interrupted, we can retry */ switch (errno) { @@ -168,13 +171,13 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src) GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno))); break; case EIO: - GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL), - ("VIDIOC_DQBUF failed due to an internal error." - " Can also indicate temporary problems like signal loss." - " Note the driver might dequeue an (empty) buffer despite" - " returning an error, or even stop capturing." - " device %s: %s", - GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2src, + "VIDIOC_DQBUF failed due to an internal error." + " Can also indicate temporary problems like signal loss." + " Note the driver might dequeue an (empty) buffer despite" + " returning an error, or even stop capturing." + " device %s: %s", + GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)); break; case EINTR: GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL), @@ -186,7 +189,14 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src) break; } - return -1; + if (--trials == -1) { + return -1; + } else { + ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_QBUF, &buffer); + memset (&buffer, 0x00, sizeof (buffer)); + buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buffer.memory = v4l2src->breq.memory; + } } @@ -292,8 +302,8 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src) GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (_("Could not get buffers from device \"%s\"."), GST_V4L2ELEMENT (v4l2src)->videodev), - ("error requesting %d buffers: %s", v4l2src->breq.count, - g_strerror (errno))); + ("error requesting %d buffers: %s", + v4l2src->breq.count, g_strerror (errno))); return FALSE; } GST_LOG_OBJECT (v4l2src, "using default mmap method"); @@ -314,8 +324,8 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src) GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (_("Could not get enough buffers from device \"%s\"."), GST_V4L2ELEMENT (v4l2src)->videodev), - ("we received %d, we want at least %d", v4l2src->breq.count, - GST_V4L2_MIN_BUFFERS)); + ("we received %d, we want at least %d", + v4l2src->breq.count, GST_V4L2_MIN_BUFFERS)); v4l2src->breq.count = buffers; return FALSE; } @@ -347,8 +357,8 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src) if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_QUERYBUF, &buffer->buffer) < 0) { GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL), - ("Could not get buffer properties of buffer %d: %s", n, - g_strerror (errno))); + ("Could not get buffer properties of buffer %d: %s", + n, g_strerror (errno))); gst_v4l2src_capture_deinit (v4l2src); return FALSE; } @@ -772,7 +782,10 @@ gst_v4l2src_buffer_new (GstV4l2Src * v4l2src, guint size, guint8 * data, GST_DEBUG_OBJECT (v4l2src, "creating buffer %d"); - g_return_val_if_fail (gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d), NULL); + if (!gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d)) { + fps_n = 0; + fps_d = 1; + } buf = (GstBuffer *) gst_mini_object_new (GST_TYPE_V4L2SRC_BUFFER); @@ -790,8 +803,12 @@ gst_v4l2src_buffer_new (GstV4l2Src * v4l2src, guint size, guint8 * data, GST_BUFFER_TIMESTAMP (buf) -= GST_ELEMENT (v4l2src)->base_time; GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY); - GST_BUFFER_DURATION (buf) = gst_util_uint64_scale_int (GST_SECOND, - fps_n, fps_d); + if (fps_n > 0) { + GST_BUFFER_DURATION (buf) = gst_util_uint64_scale_int (GST_SECOND, + fps_n, fps_d); + } else { + GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; + } /* the negotiate() method already set caps on the source pad */ gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4l2src))); diff --git a/sys/v4l2/v4l2src_calls.h b/sys/v4l2/v4l2src_calls.h index 87667611..1411083e 100644 --- a/sys/v4l2/v4l2src_calls.h +++ b/sys/v4l2/v4l2src_calls.h @@ -24,38 +24,36 @@ #include "v4l2_calls.h" -gboolean gst_v4l2src_get_capture (GstV4l2Src *v4l2src); -gboolean gst_v4l2src_set_capture (GstV4l2Src *v4l2src, - struct v4l2_fmtdesc *fmt, - gint width, - gint height); -gboolean gst_v4l2src_capture_init (GstV4l2Src *v4l2src); -gboolean gst_v4l2src_capture_start (GstV4l2Src *v4l2src); -gint gst_v4l2src_grab_frame (GstV4l2Src *v4l2src); - -gboolean gst_v4l2src_queue_frame (GstV4l2Src *v4l2src, - guint i); -gboolean gst_v4l2src_capture_stop (GstV4l2Src *v4l2src); -gboolean gst_v4l2src_capture_deinit (GstV4l2Src *v4l2src); - -gboolean gst_v4l2src_fill_format_list (GstV4l2Src *v4l2src); -gboolean gst_v4l2src_clear_format_list (GstV4l2Src *v4l2src); +gboolean gst_v4l2src_get_capture (GstV4l2Src * v4l2src); +gboolean gst_v4l2src_set_capture (GstV4l2Src * v4l2src, + struct v4l2_fmtdesc *fmt, + gint width, gint height); +gboolean gst_v4l2src_capture_init (GstV4l2Src * v4l2src); +gboolean gst_v4l2src_capture_start (GstV4l2Src * v4l2src); +gint gst_v4l2src_grab_frame (GstV4l2Src * v4l2src); + +gboolean gst_v4l2src_queue_frame (GstV4l2Src * v4l2src, guint i); +gboolean gst_v4l2src_capture_stop (GstV4l2Src * v4l2src); +gboolean gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src); + +gboolean gst_v4l2src_fill_format_list (GstV4l2Src * v4l2src); +gboolean gst_v4l2src_clear_format_list (GstV4l2Src * v4l2src); /* hacky */ -gboolean gst_v4l2src_get_size_limits (GstV4l2Src *v4l2src, - struct v4l2_fmtdesc *fmt, - gint *min_w, gint *max_w, - gint *min_h, gint *max_h); +gboolean gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src, + struct v4l2_fmtdesc *fmt, + gint * min_w, gint * max_w, + gint * min_h, gint * max_h); + +void gst_v4l2src_free_buffer (GstBuffer * buffer); -void gst_v4l2src_free_buffer (GstBuffer *buffer); +gboolean gst_v4l2src_get_fps (GstV4l2Src * v4l2src, gint * fps_n, gint * fps_d); -gboolean gst_v4l2src_get_fps (GstV4l2Src * v4l2src, gint * fps_n, gint * fps_d); +GValue *gst_v4l2src_get_fps_list (GstV4l2Src * v4l2src); -GValue * gst_v4l2src_get_fps_list (GstV4l2Src * v4l2src); +GstBuffer *gst_v4l2src_buffer_new (GstV4l2Src * v4l2src, + guint size, guint8 * data, + GstV4l2Buffer * srcbuf); -GstBuffer * gst_v4l2src_buffer_new (GstV4l2Src * v4l2src, - guint size, guint8 * data, - GstV4l2Buffer * srcbuf); - #endif /* __V4L2SRC_CALLS_H__ */ |