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:
Stefan Kost 2007-01-17 14:30:50 +00:00
parent 703a0d00d8
commit fdd167aeb1
5 changed files with 93 additions and 65 deletions

View file

@ -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>

View file

@ -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");
*/
}
}
}

View file

@ -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,

View file

@ -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;
}

View file

@ -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;
}
}