+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>
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 *
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);
v4l2object->frequency = g_value_get_ulong (value);
}
break;
+#endif
default:
return FALSE;
break;
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;
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");
-*/
}
}
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)) {
/* guess */
gst_tuner_set_frequency (tuner, channel, 1000);
} else {
-/* FIXME: remove
- g_object_notify (G_OBJECT (v4l2object->element), "frequency");
-*/
}
}
}
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,
"Ronald Bultje <rbultje@ronald.bitfreak.net>,"
" Edgard Lima <edgard.lima@indt.org.br>");
-
GST_DEBUG_CATEGORY (v4l2src_debug);
#define GST_CAT_DEFAULT v4l2src_debug
{
PROP_0,
V4L2_STD_OBJECT_PROPS,
+ PROP_QUEUE_SIZE
};
static const guint32 gst_v4l2_formats[] = {
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;
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;
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;
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;
/* 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))
/* 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;
}
gint
gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
{
-#define NUM_TRIALS 100
+#define NUM_TRIALS 50
struct v4l2_buffer buffer;
gint32 trials = NUM_TRIALS;
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:
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,
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;
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));
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;
- }
}
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);
/* 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) {
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",
}
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;
}
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;
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;
}
}