From 21dadc64490a2e99c7f0b83977047b348071d883 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Tue, 27 Apr 2004 11:33:52 +0000 Subject: [PATCH] fix v4l for qc-usb webcams Original commit message from CVS: fix v4l for qc-usb webcams --- ChangeLog | 12 ++++++++++ sys/v4l/gstv4l.c | 4 ++++ sys/v4l/gstv4lsrc.c | 52 ++++++++++++++++++++++++++++++------------ sys/v4l/v4l_calls.c | 5 ++++ sys/v4l/v4lsrc_calls.c | 6 +++++ 5 files changed, 64 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2d4d6f1ef0..8f8596821c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2004-04-27 Thomas Vander Stichele + + * Makefile.am: + * sys/v4l/gstv4l.c: + * sys/v4l/gstv4lsrc.c: + * sys/v4l/v4l_calls.c: + * sys/v4l/v4lsrc_calls.c: + fix for qc-usb driver which fakes having more than one buffer + by handing the same buffer twice, which confused GStreamer's/v4lsrc + buffer_free override + add debugging + 2004-04-27 Thomas Vander Stichele * Makefile.am: diff --git a/sys/v4l/gstv4l.c b/sys/v4l/gstv4l.c index b3f9c5011d..1984a08a5a 100644 --- a/sys/v4l/gstv4l.c +++ b/sys/v4l/gstv4l.c @@ -30,9 +30,13 @@ #include "gstv4lmjpegsrc.h" #include "gstv4lmjpegsink.h" +GST_DEBUG_CATEGORY (v4l_debug); /* used in v4l_calls.c and v4lsrc_calls.c */ + static gboolean plugin_init (GstPlugin * plugin) { + GST_DEBUG_CATEGORY_INIT (v4l_debug, "v4l", 0, "V4L API calls"); + /* actually, we can survive without it, but I'll create * that handling later on. */ if (!gst_library_load ("xwindowlistener")) diff --git a/sys/v4l/gstv4lsrc.c b/sys/v4l/gstv4lsrc.c index 2bd6d95d48..c100465f9a 100644 --- a/sys/v4l/gstv4lsrc.c +++ b/sys/v4l/gstv4lsrc.c @@ -32,6 +32,9 @@ GST_ELEMENT_DETAILS ("Video (video4linux/raw) Source", "Reads raw frames from a video4linux (BT8x8) device", "Ronald Bultje "); +GST_DEBUG_CATEGORY (v4lsrc_debug); +#define GST_CAT_DEFAULT v4lsrc_debug + /* V4lSrc signals and args */ enum { @@ -56,6 +59,14 @@ GST_FORMATS_FUNCTION (GstPad *, gst_v4lsrc_get_formats, GST_QUERY_TYPE_FUNCTION (GstPad *, gst_v4lsrc_get_query_types, GST_QUERY_POSITION); +/* structure for buffer private data referencing element and frame number */ +typedef struct +{ + GstV4lSrc *v4lsrc; + int num; +} +v4lsrc_private_t; + /* init functions */ static void gst_v4lsrc_base_init (gpointer g_class); static void gst_v4lsrc_class_init (GstV4lSrcClass * klass); @@ -176,6 +187,7 @@ gst_v4lsrc_class_init (GstV4lSrcClass * klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstV4lSrcClass, frame_insert), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + GST_DEBUG_CATEGORY_INIT (v4lsrc_debug, "v4lsrc", 0, "V4L source element"); gobject_class->set_property = gst_v4lsrc_set_property; gobject_class->get_property = gst_v4lsrc_get_property; @@ -601,6 +613,7 @@ gst_v4lsrc_get (GstPad * pad) GstBuffer *buf; gint num; gdouble fps = 0.; + v4lsrc_private_t *v4lsrc_private = NULL; g_return_val_if_fail (pad != NULL, NULL); @@ -670,7 +683,13 @@ gst_v4lsrc_get (GstPad * pad) buf = gst_buffer_new (); GST_BUFFER_FREE_DATA_FUNC (buf) = gst_v4lsrc_buffer_free; - GST_BUFFER_PRIVATE (buf) = v4lsrc; /* hack to re-queue buffer on free */ + /* to requeue buffers, we need a ref to the element, as well as the frame + number we got this buffer from */ + v4lsrc_private = g_malloc (sizeof (v4lsrc_private_t)); + v4lsrc_private->v4lsrc = v4lsrc; + v4lsrc_private->num = num; + GST_BUFFER_PRIVATE (buf) = v4lsrc_private; + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_READONLY | GST_BUFFER_DONTFREE); GST_BUFFER_DATA (buf) = gst_v4lsrc_get_buffer (v4lsrc, num); GST_BUFFER_MAXSIZE (buf) = v4lsrc->mbuf.size / v4lsrc->mbuf.frames; @@ -826,24 +845,27 @@ gst_v4lsrc_buffer_new (GstBufferPool * pool, static void gst_v4lsrc_buffer_free (GstBuffer * buf) { - GstV4lSrc *v4lsrc = GST_V4LSRC (GST_BUFFER_PRIVATE (buf)); - int n; + v4lsrc_private_t *v4lsrc_private; + GstV4lSrc *v4lsrc; + int num; + v4lsrc_private = GST_BUFFER_PRIVATE (buf); + g_assert (v4lsrc_private); + v4lsrc = v4lsrc_private->v4lsrc; + num = v4lsrc_private->num; + g_free (v4lsrc_private); + GST_BUFFER_PRIVATE (buf) = 0; + + GST_DEBUG_OBJECT (v4lsrc, "freeing buffer %p with refcount %d for frame %d", + buf, GST_BUFFER_REFCOUNT_VALUE (buf), num); if (gst_element_get_state (GST_ELEMENT (v4lsrc)) != GST_STATE_PLAYING) return; /* we've already cleaned up ourselves */ - for (n = 0; n < v4lsrc->mbuf.frames; n++) - if (GST_BUFFER_DATA (buf) == gst_v4lsrc_get_buffer (v4lsrc, n)) { - v4lsrc->use_num_times[n]--; - if (v4lsrc->use_num_times[n] <= 0) { - gst_v4lsrc_requeue_frame (v4lsrc, n); - } - break; - } - - if (n == v4lsrc->mbuf.frames) - GST_ELEMENT_ERROR (v4lsrc, RESOURCE, TOO_LAZY, (NULL), - ("Couldn\'t find the buffer")); + v4lsrc->use_num_times[num]--; + if (v4lsrc->use_num_times[num] <= 0) { + GST_DEBUG_OBJECT (v4lsrc, "requeueing frame %d", num); + gst_v4lsrc_requeue_frame (v4lsrc, num); + } } diff --git a/sys/v4l/v4l_calls.c b/sys/v4l/v4l_calls.c index a007f622de..22a1bd7921 100644 --- a/sys/v4l/v4l_calls.c +++ b/sys/v4l/v4l_calls.c @@ -42,6 +42,11 @@ #include "gstv4lmjpegsrc.h" #include "gstv4lmjpegsink.h" + +GST_DEBUG_CATEGORY_EXTERN (v4l_debug); + +#define GST_CATEGORY_DEFAULT v4l_debug + #define DEBUG(format, args...) \ GST_DEBUG_OBJECT (\ GST_ELEMENT(v4lelement), \ diff --git a/sys/v4l/v4lsrc_calls.c b/sys/v4l/v4lsrc_calls.c index a85a99e708..d036cfa8d8 100644 --- a/sys/v4l/v4lsrc_calls.c +++ b/sys/v4l/v4lsrc_calls.c @@ -40,6 +40,10 @@ #define MAP_FAILED ( (caddr_t) -1 ) #endif +GST_DEBUG_CATEGORY_EXTERN (v4l_debug); + +#define GST_CAT_DEFAULT v4l_debug + #define DEBUG(format, args...) \ GST_DEBUG_OBJECT (\ GST_ELEMENT(v4lsrc), \ @@ -302,6 +306,8 @@ gst_v4lsrc_grab_frame (GstV4lSrc * v4lsrc, gint * num) } v4lsrc->sync_frame = (v4lsrc->sync_frame + 1) % v4lsrc->mbuf.frames; + GST_DEBUG ("grabbed frame %d", *num); + g_mutex_unlock (v4lsrc->mutex_queue_state); return TRUE;