diff --git a/ChangeLog b/ChangeLog index 1cf78e70c8..e2904b3c46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2004-06-17 Thomas Vander Stichele + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init), (gst_v4lsrc_init), + (gst_v4lsrc_open), (gst_v4lsrc_src_link), (gst_v4lsrc_getcaps), + (gst_v4lsrc_get), (gst_v4lsrc_set_property), + (gst_v4lsrc_get_property): + * sys/v4l/gstv4lsrc.h: + * sys/v4l/v4l_calls.c: (gst_v4l_set_window_properties), + (gst_v4l_open), (gst_v4l_get_picture), (gst_v4l_get_audio), + (gst_v4l_set_audio): + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_grab_frame), + (gst_v4lsrc_try_capture): + * sys/v4l/v4lsrc_calls.h: + change try_palette to more general try_capture + add autoprobe option so we can turn off autoprobing + various fixes + 2004-06-17 Thomas Vander Stichele * configure.ac: diff --git a/sys/v4l/gstv4lsrc.c b/sys/v4l/gstv4lsrc.c index 6057e86c9b..9a075b2aa7 100644 --- a/sys/v4l/gstv4lsrc.c +++ b/sys/v4l/gstv4lsrc.c @@ -31,6 +31,7 @@ /* FIXME: small cheat */ gboolean gst_v4l_set_window_properties (GstV4lElement * v4lelement); +gboolean gst_v4l_get_capabilities (GstV4lElement * v4lelement); /* elementfactory information */ static GstElementDetails gst_v4lsrc_details = @@ -61,7 +62,8 @@ enum ARG_NUMBUFS, ARG_BUFSIZE, ARG_SYNC_MODE, - ARG_COPY_MODE + ARG_COPY_MODE, + ARG_AUTOPROBE }; GST_FORMATS_FUNCTION (GstPad *, gst_v4lsrc_get_formats, @@ -114,7 +116,7 @@ static gboolean gst_v4lsrc_src_query (GstPad * pad, GstQueryType type, GstFormat * format, gint64 * value); /* buffer functions */ -static GstPadLinkReturn gst_v4lsrc_srcconnect (GstPad * pad, +static GstPadLinkReturn gst_v4lsrc_src_link (GstPad * pad, const GstCaps * caps); static GstCaps *gst_v4lsrc_fixate (GstPad * pad, const GstCaps * caps); static GstCaps *gst_v4lsrc_getcaps (GstPad * pad); @@ -206,6 +208,10 @@ gst_v4lsrc_class_init (GstV4lSrcClass * klass) g_param_spec_boolean ("copy_mode", "Copy mode", "Don't send out HW buffers, send copy instead", DEFAULT_COPY_MODE, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_AUTOPROBE, + g_param_spec_boolean ("autoprobe", "Autoprobe", + "Whether the device should be probed for all possible features", + TRUE, G_PARAM_READWRITE)); /* signals */ gst_v4lsrc_signals[SIGNAL_FRAME_CAPTURE] = @@ -233,7 +239,6 @@ gst_v4lsrc_class_init (GstV4lSrcClass * klass) v4lelement_class->close = gst_v4lsrc_close; } - static void gst_v4lsrc_init (GstV4lSrc * v4lsrc) { @@ -249,7 +254,7 @@ gst_v4lsrc_init (GstV4lSrc * v4lsrc) gst_pad_set_get_function (v4lsrc->srcpad, gst_v4lsrc_get); gst_pad_set_getcaps_function (v4lsrc->srcpad, gst_v4lsrc_getcaps); gst_pad_set_fixate_function (v4lsrc->srcpad, gst_v4lsrc_fixate); - gst_pad_set_link_function (v4lsrc->srcpad, gst_v4lsrc_srcconnect); + gst_pad_set_link_function (v4lsrc->srcpad, gst_v4lsrc_src_link); gst_pad_set_convert_function (v4lsrc->srcpad, gst_v4lsrc_src_convert); gst_pad_set_formats_function (v4lsrc->srcpad, gst_v4lsrc_get_formats); gst_pad_set_query_function (v4lsrc->srcpad, gst_v4lsrc_src_query); @@ -267,12 +272,17 @@ gst_v4lsrc_init (GstV4lSrc * v4lsrc) v4lsrc->copy_mode = DEFAULT_COPY_MODE; v4lsrc->is_capturing = FALSE; + v4lsrc->autoprobe = TRUE; } static void gst_v4lsrc_open (GstElement * element, const gchar * device) { GstV4lSrc *v4lsrc = GST_V4LSRC (element); + GstV4lElement *v4l = GST_V4LELEMENT (v4lsrc); + gint width = v4l->vcap.minwidth; + gint height = v4l->vcap.minheight; + int palette[] = { VIDEO_PALETTE_YUV422, VIDEO_PALETTE_YUV420P, @@ -290,7 +300,7 @@ gst_v4lsrc_open (GstElement * element, const gchar * device) for (i = 0; palette[i] != -1; i++) { /* try palette out */ - if (!gst_v4lsrc_try_palette (v4lsrc, palette[i])) + if (!gst_v4lsrc_try_capture (v4lsrc, width, height, palette[i])) continue; v4lsrc->colourspaces = g_list_append (v4lsrc->colourspaces, GINT_TO_POINTER (palette[i])); @@ -575,7 +585,7 @@ gst_v4lsrc_palette_to_caps (int palette) static GstPadLinkReturn -gst_v4lsrc_srcconnect (GstPad * pad, const GstCaps * vscapslist) +gst_v4lsrc_src_link (GstPad * pad, const GstCaps * vscapslist) { GstV4lSrc *v4lsrc; guint32 fourcc; @@ -583,8 +593,10 @@ gst_v4lsrc_srcconnect (GstPad * pad, const GstCaps * vscapslist) gdouble fps; GstStructure *structure; gboolean was_capturing; + struct video_window *vwin; v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad)); + vwin = &GST_V4LELEMENT (v4lsrc)->vwin; was_capturing = v4lsrc->is_capturing; /* in case the buffers are active (which means that we already @@ -614,7 +626,6 @@ gst_v4lsrc_srcconnect (GstPad * pad, const GstCaps * vscapslist) /* set framerate if it's not already correct */ if (fps != gst_v4lsrc_get_fps (v4lsrc)) { int fps_index = fps / 15.0 * 16; - struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin; GST_DEBUG_OBJECT (v4lsrc, "Trying to set fps index %d", fps_index); /* set bits 16 to 21 to 0 */ @@ -689,11 +700,46 @@ gst_v4lsrc_srcconnect (GstPad * pad, const GstCaps * vscapslist) break; } - if (palette == -1) + if (palette == -1) { + GST_WARN_OBJECT (v4lsrc, "palette is -1, refusing link"); return GST_PAD_LINK_REFUSED; + } - if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) + GST_DEBUG_OBJECT (v4lsrc, "trying to set_capture %dx%d, palette %d", + w, h, palette); + if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) { + GST_WARN_OBJECT (v4lsrc, "could not set_capture %dx%d, palette %d", + w, h, palette); return GST_PAD_LINK_REFUSED; + } + + /* first try the negotiated settings using try_capture */ + if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) { + GST_DEBUG_OBJECT (v4lsrc, "failed trying palette %d for w/h", palette); + return GST_PAD_LINK_REFUSED; + } + if (!gst_v4l_get_capabilities (GST_V4LELEMENT (v4lsrc))) + GST_DEBUG_OBJECT (v4lsrc, "failed getting capabilities"); + GST_DEBUG_OBJECT (v4lsrc, "done checking, with w %d h %d palette %d\n", + vwin->width, vwin->height, palette); + if (vwin->width != v4lsrc->mmap.width) { + /* We consider this a device error since it was called with fixed + * caps that the device doesn't accept. Still, there should be + * a way to handle this more gracefully, maybe provide a fixate + * function */ + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, SETTINGS, (NULL), + ("Tried setting %dx%d but got %dx%d back as suggestion", + v4lsrc->mmap.width, v4lsrc->mmap.height, vwin->width, + vwin->height)); + return GST_PAD_LINK_REFUSED; + } + if (vwin->height != v4lsrc->mmap.height) { + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, SETTINGS, (NULL), + ("Tried setting %dx%d but got %dx%d back as suggestion", + v4lsrc->mmap.width, v4lsrc->mmap.height, vwin->width, + vwin->height)); + return GST_PAD_LINK_REFUSED; + } if (!gst_v4lsrc_capture_init (v4lsrc)) return GST_PAD_LINK_REFUSED; @@ -752,6 +798,11 @@ gst_v4lsrc_getcaps (GstPad * pad) if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) { return gst_caps_new_any (); } + if (!v4lsrc->autoprobe) { + /* FIXME: query current caps and return those, with _any appended */ + return gst_caps_new_any (); + } + /* if not cached from last run, get it */ if (!fps_list) fps_list = gst_v4lsrc_get_fps_list (v4lsrc); @@ -907,7 +958,8 @@ gst_v4lsrc_get (GstPad * pad) if (v4lsrc->clock) { GstClockTime time = gst_element_get_time (GST_ELEMENT (v4lsrc)); - GST_BUFFER_TIMESTAMP (buf) = time; + /* FIXME: figure out a way to add the capture latency here */ + GST_BUFFER_TIMESTAMP (buf) = time /* + 0.5 * GST_SECOND / fps */ ; } else { GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE; } @@ -990,6 +1042,12 @@ gst_v4lsrc_set_property (GObject * object, v4lsrc->copy_mode = g_value_get_boolean (value); break; + case ARG_AUTOPROBE: + if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))) { + v4lsrc->autoprobe = g_value_get_boolean (value); + } + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1027,6 +1085,10 @@ gst_v4lsrc_get_property (GObject * object, g_value_set_boolean (value, v4lsrc->copy_mode); break; + case ARG_AUTOPROBE: + g_value_set_boolean (value, v4lsrc->autoprobe); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/sys/v4l/gstv4lsrc.h b/sys/v4l/gstv4lsrc.h index 0a6b4d8825..27797f7134 100644 --- a/sys/v4l/gstv4lsrc.h +++ b/sys/v4l/gstv4lsrc.h @@ -103,6 +103,7 @@ struct _GstV4lSrc GstV4lSrcSyncMode syncmode; gboolean copy_mode; + gboolean autoprobe; /* probe on startup ? */ }; struct _GstV4lSrcClass diff --git a/sys/v4l/v4l_calls.c b/sys/v4l/v4l_calls.c index 6e6cb8e96f..c115e93779 100644 --- a/sys/v4l/v4l_calls.c +++ b/sys/v4l/v4l_calls.c @@ -76,7 +76,7 @@ static const char *norm_name[] = { * return value: TRUE on success, FALSE on error ******************************************************/ -static gboolean +gboolean gst_v4l_get_capabilities (GstV4lElement * v4lelement) { GST_DEBUG_OBJECT (v4lelement, "getting capabilities"); @@ -194,7 +194,7 @@ gst_v4l_open (GstV4lElement * v4lelement) return FALSE; } - GST_INFO_OBJECT (v4lelement, "Opened device \'%s\' (\'%s\') successfully\n", + GST_INFO_OBJECT (v4lelement, "Opened device \'%s\' (\'%s\') successfully", v4lelement->vcap.name, v4lelement->videodev); /* norms + inputs, for the tuner interface */ diff --git a/sys/v4l/v4lsrc_calls.c b/sys/v4l/v4lsrc_calls.c index 6cf1df18a9..41fd5753d5 100644 --- a/sys/v4l/v4lsrc_calls.c +++ b/sys/v4l/v4lsrc_calls.c @@ -274,7 +274,7 @@ gst_v4lsrc_capture_start (GstV4lSrc * v4lsrc) gboolean gst_v4lsrc_grab_frame (GstV4lSrc * v4lsrc, gint * num) { - GST_LOG_OBJECT (v4lsrc, "grabbing frame"); + GST_LOG_OBJECT (v4lsrc, "grabbing frame %d", num); GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc)); GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc)); @@ -443,10 +443,9 @@ gst_v4lsrc_capture_deinit (GstV4lSrc * v4lsrc) return TRUE; } - /****************************************************** - * gst_v4lsrc_try_palette(): - * try out a palette on the device + * gst_v4lsrc_try_capture(): + * try out a capture on the device * This has to be done before initializing the * actual capture system, to make sure we don't * mess up anything. So we need to mini-mmap() @@ -461,7 +460,8 @@ gst_v4lsrc_capture_deinit (GstV4lSrc * v4lsrc) ******************************************************/ gboolean -gst_v4lsrc_try_palette (GstV4lSrc * v4lsrc, gint palette) +gst_v4lsrc_try_capture (GstV4lSrc * v4lsrc, gint width, gint height, + gint palette) { /* so, we need a buffer and some more stuff */ int frame = 0; @@ -469,8 +469,8 @@ gst_v4lsrc_try_palette (GstV4lSrc * v4lsrc, gint palette) struct video_mbuf vmbuf; struct video_mmap vmmap; - GST_DEBUG_OBJECT (v4lsrc, "gonna try out palette format %d (%s)", - palette, palette_name[palette]); + GST_DEBUG_OBJECT (v4lsrc, "try out %dx%d, palette format %d (%s)", + width, height, palette, palette_name[palette]); GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc)); GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lsrc)); @@ -490,8 +490,8 @@ gst_v4lsrc_try_palette (GstV4lSrc * v4lsrc, gint palette) } /* now that we have a buffer, let's try out our format */ - vmmap.width = GST_V4LELEMENT (v4lsrc)->vcap.minwidth; - vmmap.height = GST_V4LELEMENT (v4lsrc)->vcap.minheight; + vmmap.width = width; + vmmap.height = height; vmmap.format = palette; vmmap.frame = frame; if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCMCAPTURE, &vmmap) < 0) { diff --git a/sys/v4l/v4lsrc_calls.h b/sys/v4l/v4lsrc_calls.h index 9b013fc7b7..8ff1d7787c 100644 --- a/sys/v4l/v4lsrc_calls.h +++ b/sys/v4l/v4lsrc_calls.h @@ -42,7 +42,7 @@ gboolean gst_v4lsrc_capture_stop (GstV4lSrc *v4lsrc); gboolean gst_v4lsrc_capture_deinit (GstV4lSrc *v4lsrc); /* "the ugliest hack ever, now available at your local mirror" */ -gboolean gst_v4lsrc_try_palette (GstV4lSrc *v4lsrc, gint palette); +gboolean gst_v4lsrc_try_capture (GstV4lSrc *v4lsrc, gint width, gint height, gint palette); #ifdef __cplusplus