mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
sys/v4l2/: Fix EIO handing when capturing. Add new property to specify the number of buffers to enque (and remove the...
Original commit message from CVS: * sys/v4l2/gstv4l2object.c: (gst_v4l2_object_install_properties_helper), (gst_v4l2_object_set_property_helper), (gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults): * sys/v4l2/gstv4l2object.h: * sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init), (gst_v4l2src_init), (gst_v4l2src_set_property), (gst_v4l2src_get_property), (gst_v4l2src_set_caps): * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list), (gst_v4l2src_grab_frame), (gst_v4l2src_set_capture), (gst_v4l2src_capture_init), (gst_v4l2src_capture_start), (gst_v4l2src_capture_deinit): Fix EIO handing when capturing. Add new property to specify the number of buffers to enque (and remove the borked num-buffers usage).
This commit is contained in:
parent
703a0d00d8
commit
fdd167aeb1
5 changed files with 93 additions and 65 deletions
29
ChangeLog
29
ChangeLog
|
@ -1,3 +1,32 @@
|
|||
2007-01-17 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* sys/v4l2/gstv4l2object.c:
|
||||
(gst_v4l2_object_install_properties_helper),
|
||||
(gst_v4l2_object_set_property_helper),
|
||||
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults):
|
||||
* sys/v4l2/gstv4l2object.h:
|
||||
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
|
||||
(gst_v4l2src_init), (gst_v4l2src_set_property),
|
||||
(gst_v4l2src_get_property), (gst_v4l2src_set_caps):
|
||||
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
|
||||
(gst_v4l2src_grab_frame), (gst_v4l2src_set_capture),
|
||||
(gst_v4l2src_capture_init), (gst_v4l2src_capture_start),
|
||||
(gst_v4l2src_capture_deinit):
|
||||
Fix EIO handing when capturing. Add new property to specify the number of
|
||||
buffers to enque (and remove the borked num-buffers usage).
|
||||
|
||||
2007-01-16 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_query),
|
||||
(gst_avi_demux_parse_index), (gst_avi_demux_stream_index),
|
||||
(gst_avi_demux_sync), (gst_avi_demux_next_data_buffer),
|
||||
(gst_avi_demux_stream_scan), (gst_avi_demux_massage_index),
|
||||
(gst_avi_demux_calculate_durations_from_index),
|
||||
(gst_avi_demux_push_event), (gst_avi_demux_stream_header_pull),
|
||||
(gst_avi_demux_handle_seek), (gst_avi_demux_stream_data),
|
||||
(gst_avi_demux_loop):
|
||||
Fix hanging when demuxing fuzzed file (#397229). Add some more debug.
|
||||
|
||||
2007-01-16 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
Patch by: Sebastian Dröge <slomo circular-chaos org>
|
||||
|
|
|
@ -244,20 +244,6 @@ gst_v4l2_object_install_properties_helper (GObjectClass * gobject_class)
|
|||
g_object_class_install_property (gobject_class, PROP_FLAGS,
|
||||
g_param_spec_flags ("flags", "Flags", "Device type flags",
|
||||
GST_TYPE_V4L2_DEVICE_FLAGS, DEFAULT_PROP_FLAGS, G_PARAM_READABLE));
|
||||
/* FIXME norm, channel, frequency are part of the tuner interface, so they
|
||||
should be removed from the properties
|
||||
g_object_class_install_property (gobject_class, PROP_NORM,
|
||||
g_param_spec_string ("norm", "Norm", "Standard norm to use",
|
||||
DEFAULT_PROP_NORM, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, PROP_CHANNEL,
|
||||
g_param_spec_string ("channel", "Channel",
|
||||
"Input/output channel to switch to", DEFAULT_PROP_CHANNEL,
|
||||
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, DEFAULT_PROP_FREQUENCY,
|
||||
G_PARAM_READWRITE));
|
||||
*/
|
||||
}
|
||||
|
||||
GstV4l2Object *
|
||||
|
@ -314,6 +300,7 @@ gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
|
|||
g_free (v4l2object->videodev);
|
||||
v4l2object->videodev = g_value_dup_string (value);
|
||||
break;
|
||||
#if 0
|
||||
case PROP_NORM:
|
||||
if (GST_V4L2_IS_OPEN (v4l2object)) {
|
||||
GstTuner *tuner = GST_TUNER (v4l2object->element);
|
||||
|
@ -363,6 +350,7 @@ gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
|
|||
v4l2object->frequency = g_value_get_ulong (value);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return FALSE;
|
||||
break;
|
||||
|
@ -407,15 +395,6 @@ gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
|
|||
g_value_set_flags (value, flags);
|
||||
break;
|
||||
}
|
||||
case PROP_NORM:
|
||||
g_value_set_string (value, v4l2object->norm);
|
||||
break;
|
||||
case PROP_CHANNEL:
|
||||
g_value_set_string (value, v4l2object->channel);
|
||||
break;
|
||||
case PROP_FREQUENCY:
|
||||
g_value_set_ulong (value, v4l2object->frequency);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
break;
|
||||
|
@ -441,9 +420,6 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
|
|||
g_free (v4l2object->norm);
|
||||
v4l2object->norm = g_strdup (norm->label);
|
||||
gst_tuner_norm_changed (tuner, norm);
|
||||
/* FIXME: remove
|
||||
g_object_notify (G_OBJECT (v4l2object->element), "norm");
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,9 +434,6 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
|
|||
g_free (v4l2object->channel);
|
||||
v4l2object->channel = g_strdup (channel->label);
|
||||
gst_tuner_channel_changed (tuner, channel);
|
||||
/* FIXME: remove
|
||||
g_object_notify (G_OBJECT (v4l2object->element), "channel");
|
||||
*/
|
||||
}
|
||||
|
||||
if (GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
|
||||
|
@ -472,9 +445,6 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
|
|||
/* guess */
|
||||
gst_tuner_set_frequency (tuner, channel, 1000);
|
||||
} else {
|
||||
/* FIXME: remove
|
||||
g_object_notify (G_OBJECT (v4l2object->element), "frequency");
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,16 +105,12 @@ struct _GstV4l2ObjectClassHelper {
|
|||
GList *devices;
|
||||
};
|
||||
|
||||
GType gst_v4l2_object_get_type(void);
|
||||
|
||||
#define V4L2_STD_OBJECT_PROPS \
|
||||
PROP_DEVICE, \
|
||||
PROP_DEVICE_NAME, \
|
||||
PROP_FLAGS, \
|
||||
PROP_NORM, \
|
||||
PROP_CHANNEL, \
|
||||
PROP_FREQUENCY
|
||||
GType gst_v4l2_object_get_type (void);
|
||||
|
||||
#define V4L2_STD_OBJECT_PROPS \
|
||||
PROP_DEVICE, \
|
||||
PROP_DEVICE_NAME, \
|
||||
PROP_FLAGS
|
||||
|
||||
/* create/destroy */
|
||||
GstV4l2Object * gst_v4l2_object_new (GstElement * element,
|
||||
|
|
|
@ -58,7 +58,6 @@ GST_ELEMENT_DETAILS ("Video (video4linux2/raw) Source",
|
|||
"Ronald Bultje <rbultje@ronald.bitfreak.net>,"
|
||||
" Edgard Lima <edgard.lima@indt.org.br>");
|
||||
|
||||
|
||||
GST_DEBUG_CATEGORY (v4l2src_debug);
|
||||
#define GST_CAT_DEFAULT v4l2src_debug
|
||||
|
||||
|
@ -66,6 +65,7 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
V4L2_STD_OBJECT_PROPS,
|
||||
PROP_QUEUE_SIZE
|
||||
};
|
||||
|
||||
static const guint32 gst_v4l2_formats[] = {
|
||||
|
@ -274,6 +274,11 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
|
|||
gobject_class->get_property = gst_v4l2src_get_property;
|
||||
|
||||
gst_v4l2_object_install_properties_helper (gobject_class);
|
||||
g_object_class_install_property (gobject_class, PROP_QUEUE_SIZE,
|
||||
g_param_spec_uint ("queue-size", "Queue size",
|
||||
"Number of buffers to be enqueud in the driver",
|
||||
GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, GST_V4L2_MIN_BUFFERS,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
basesrc_class->get_caps = gst_v4l2src_get_caps;
|
||||
basesrc_class->set_caps = gst_v4l2src_set_caps;
|
||||
|
@ -289,6 +294,7 @@ 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);
|
||||
|
||||
/* number of buffers requested */
|
||||
v4l2src->breq.count = 0;
|
||||
|
||||
v4l2src->formats = NULL;
|
||||
|
@ -332,6 +338,9 @@ gst_v4l2src_set_property (GObject * object,
|
|||
if (!gst_v4l2_object_set_property_helper (v4l2src->v4l2object,
|
||||
prop_id, value, pspec)) {
|
||||
switch (prop_id) {
|
||||
case PROP_QUEUE_SIZE:
|
||||
v4l2src->breq.count = g_value_get_uint (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -352,6 +361,9 @@ gst_v4l2src_get_property (GObject * object,
|
|||
if (!gst_v4l2_object_get_property_helper (v4l2src->v4l2object,
|
||||
prop_id, value, pspec)) {
|
||||
switch (prop_id) {
|
||||
case PROP_QUEUE_SIZE:
|
||||
g_value_set_uint (value, v4l2src->breq.count);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -776,6 +788,7 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
|
|||
|
||||
/* make sure we stop capturing and dealloc buffers */
|
||||
if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
|
||||
/* both will throw an element-error on failure */
|
||||
if (!gst_v4l2src_capture_stop (v4l2src))
|
||||
return FALSE;
|
||||
if (!gst_v4l2src_capture_deinit (v4l2src))
|
||||
|
@ -786,6 +799,8 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
|
|||
|
||||
/* we want our own v4l2 type of fourcc codes */
|
||||
if (!(format = gst_v4l2_caps_to_v4l2fourcc (v4l2src, structure))) {
|
||||
GST_DEBUG_OBJECT (v4l2src, "can't get capture format from caps %"
|
||||
GST_PTR_FORMAT, caps);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ qbuf_failed:
|
|||
gint
|
||||
gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
|
||||
{
|
||||
#define NUM_TRIALS 100
|
||||
#define NUM_TRIALS 50
|
||||
struct v4l2_buffer buffer;
|
||||
gint32 trials = NUM_TRIALS;
|
||||
|
||||
|
@ -158,6 +158,12 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
|
|||
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buffer.memory = v4l2src->breq.memory;
|
||||
while (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_DQBUF, &buffer) < 0) {
|
||||
|
||||
GST_LOG_OBJECT (v4l2src,
|
||||
"problem grabbing frame %ld (ix=%ld), trials=%ld, pool-ct=%d, buf.flags=%d",
|
||||
buffer.sequence, buffer.index, trials, v4l2src->pool->refcount,
|
||||
buffer.flags);
|
||||
|
||||
/* if the sync() got interrupted, we can retry */
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
|
@ -169,14 +175,31 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
|
|||
case EINVAL:
|
||||
goto einval;
|
||||
case ENOMEM:
|
||||
goto nomem;
|
||||
goto enomem;
|
||||
case EIO:
|
||||
GST_WARNING_OBJECT (v4l2src,
|
||||
GST_INFO_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", v4l2src->v4l2object->videodev);
|
||||
/* have we de-queued a buffer ? */
|
||||
if (!(buffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
|
||||
/* this fails
|
||||
if ((buffer.index >= 0) && (buffer.index < v4l2src->breq.count)) {
|
||||
GST_DEBUG_OBJECT (v4l2src, "reenqueing buffer (ix=%ld)", buffer.index);
|
||||
gst_v4l2src_queue_frame (v4l2src, buffer.index);
|
||||
}
|
||||
else {
|
||||
*/
|
||||
GST_DEBUG_OBJECT (v4l2src, "reenqueing buffer");
|
||||
if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_QBUF, &buffer) < 0) {
|
||||
GST_WARNING_OBJECT (v4l2src,
|
||||
"Error queueing buffer on device %s. system error: %s",
|
||||
v4l2src->v4l2object->videodev, g_strerror (errno));
|
||||
}
|
||||
/*} */
|
||||
}
|
||||
break;
|
||||
case EINTR:
|
||||
GST_WARNING_OBJECT (v4l2src,
|
||||
|
@ -194,15 +217,14 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
|
|||
if (--trials == -1) {
|
||||
goto too_many_trials;
|
||||
} else {
|
||||
if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_QBUF, &buffer) < 0)
|
||||
goto qbuf_failed;
|
||||
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);
|
||||
GST_LOG_OBJECT (v4l2src, "grabbed frame %ld (ix=%ld), pool-ct=%d",
|
||||
buffer.sequence, buffer.index, v4l2src->pool->refcount);
|
||||
|
||||
return buffer.index;
|
||||
|
||||
|
@ -218,7 +240,7 @@ einval:
|
|||
v4l2src->v4l2object->videodev));
|
||||
return -1;
|
||||
}
|
||||
nomem:
|
||||
enomem:
|
||||
{
|
||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED,
|
||||
(_("Failed trying to get video frames from device '%s'. Not enough memory."), v4l2src->v4l2object->videodev), (_("insufficient memory to enqueue a user pointer buffer. device %s."), v4l2src->v4l2object->videodev));
|
||||
|
@ -233,15 +255,6 @@ too_many_trials:
|
|||
NUM_TRIALS, v4l2src->v4l2object->videodev, g_strerror (errno)));
|
||||
return -1;
|
||||
}
|
||||
qbuf_failed:
|
||||
{
|
||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, WRITE,
|
||||
(_("Could not exchange data with device '%s'."),
|
||||
v4l2src->v4l2object->videodev),
|
||||
("Error queueing buffer on device %s. system error: %s",
|
||||
v4l2src->v4l2object->videodev, g_strerror (errno)));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -390,7 +403,7 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
|
|||
guint buffers;
|
||||
GstV4l2Buffer *buffer;
|
||||
|
||||
GST_DEBUG_OBJECT (v4l2src, "initting the capture system");
|
||||
GST_DEBUG_OBJECT (v4l2src, "initializing the capture system");
|
||||
|
||||
GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
|
||||
GST_V4L2_CHECK_NOT_ACTIVE (v4l2src->v4l2object);
|
||||
|
@ -398,10 +411,8 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
|
|||
/* request buffer info */
|
||||
buffers = v4l2src->breq.count;
|
||||
|
||||
if (v4l2src->breq.count > GST_V4L2_MAX_BUFFERS)
|
||||
v4l2src->breq.count = GST_V4L2_MAX_BUFFERS;
|
||||
else if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS)
|
||||
v4l2src->breq.count = GST_V4L2_MIN_BUFFERS;
|
||||
v4l2src->breq.count = CLAMP (v4l2src->breq.count, GST_V4L2_MIN_BUFFERS,
|
||||
GST_V4L2_MAX_BUFFERS);
|
||||
|
||||
v4l2src->breq.type = v4l2src->format.type;
|
||||
if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
|
||||
|
@ -429,7 +440,7 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
|
|||
goto no_buffers;
|
||||
|
||||
if (v4l2src->breq.count != buffers)
|
||||
g_object_notify (G_OBJECT (v4l2src), "num_buffers");
|
||||
g_object_notify (G_OBJECT (v4l2src), "queue-size");
|
||||
|
||||
GST_INFO_OBJECT (v4l2src,
|
||||
"Got %d buffers (%" GST_FOURCC_FORMAT ") of size %d KB",
|
||||
|
@ -532,6 +543,11 @@ mmap_failed:
|
|||
}
|
||||
queue_failed:
|
||||
{
|
||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
|
||||
(_("Could not enqueue buffers in device '%s'."),
|
||||
v4l2src->v4l2object->videodev),
|
||||
("enqueing buffer %d/%d failed. (%d - %s)",
|
||||
n, v4l2src->breq.count, errno, g_strerror (errno)));
|
||||
gst_v4l2src_capture_deinit (v4l2src);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -549,6 +565,7 @@ gst_v4l2src_capture_start (GstV4l2Src * v4l2src)
|
|||
gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
GST_DEBUG_OBJECT (v4l2src, "starting the capturing");
|
||||
//GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
|
||||
GST_V4L2_CHECK_ACTIVE (v4l2src->v4l2object);
|
||||
|
||||
v4l2src->quit = FALSE;
|
||||
|
@ -680,7 +697,8 @@ gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
|
|||
if (try_reinit) {
|
||||
gst_v4l2src_capture_start (v4l2src);
|
||||
if (!gst_v4l2src_capture_stop (v4l2src)) {
|
||||
GST_DEBUG_OBJECT (v4l2src, "failed reinit device");
|
||||
/* stop throws an element-error on failure */
|
||||
GST_WARNING_OBJECT (v4l2src, "failed reinit device");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue