diff options
| author | Stefan Kost <ensonic@users.sourceforge.net> | 2007-01-17 14:30:50 +0000 | 
|---|---|---|
| committer | Stefan Kost <ensonic@users.sourceforge.net> | 2007-01-17 14:30:50 +0000 | 
| commit | fdd167aeb1c6b502ea64bff91416f79e97d8d1d7 (patch) | |
| tree | c1ce3d341200b120261dd920dc5dc9aeca9893f5 | |
| parent | 703a0d00d8b3548cc8dcdea1b645133d035a9734 (diff) | |
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).
| -rw-r--r-- | ChangeLog | 29 | ||||
| -rw-r--r-- | sys/v4l2/gstv4l2object.c | 34 | ||||
| -rw-r--r-- | sys/v4l2/gstv4l2object.h | 14 | ||||
| -rw-r--r-- | sys/v4l2/gstv4l2src.c | 17 | ||||
| -rw-r--r-- | sys/v4l2/v4l2src_calls.c | 64 | 
5 files changed, 93 insertions, 65 deletions
@@ -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> diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index 32d1a556..7f8df175 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -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"); -*/        }      }    } diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h index 34470739..906cff99 100644 --- a/sys/v4l2/gstv4l2object.h +++ b/sys/v4l2/gstv4l2object.h @@ -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, diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index 3b28475a..862114b2 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -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;    } diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c index 79b9f692..fd956aeb 100644 --- a/sys/v4l2/v4l2src_calls.c +++ b/sys/v4l2/v4l2src_calls.c @@ -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;        }      }  | 
