diff options
author | Ronald S. Bultje <rbultje@ronald.bitfreak.net> | 2003-03-02 21:58:52 +0000 |
---|---|---|
committer | Ronald S. Bultje <rbultje@ronald.bitfreak.net> | 2003-03-02 21:58:52 +0000 |
commit | c62995f2fc0bb404616311c43e9e4177d4c18dc1 (patch) | |
tree | b7b7af383f87aa8341e6d06d91de98e678cb5433 | |
parent | ae500224ff1791a69689791901acab576d87546c (diff) | |
download | gstreamer-plugins-bad-c62995f2fc0bb404616311c43e9e4177d4c18dc1.tar.gz |
Unification of the way to speak to v4l2 and v4l elements... Also fix a segfautl when doing gst-inspect v4l2src
Original commit message from CVS:
Unification of the way to speak to v4l2 and v4l elements... Also fix a segfautl when doing gst-inspect v4l2src
-rw-r--r-- | sys/v4l2/Makefile.am | 32 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2element-marshal.list | 3 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2element.c | 99 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2element.h | 53 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2src.c | 35 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2src.h | 2 | ||||
-rw-r--r-- | sys/v4l2/v4l2-overlay_calls.c | 3 | ||||
-rw-r--r-- | sys/v4l2/v4l2_calls.c | 244 | ||||
-rw-r--r-- | sys/v4l2/v4l2_calls.h | 18 | ||||
-rw-r--r-- | sys/v4l2/v4l2src_calls.c | 50 | ||||
-rw-r--r-- | sys/v4l2/v4l2src_calls.h | 2 |
11 files changed, 213 insertions, 328 deletions
diff --git a/sys/v4l2/Makefile.am b/sys/v4l2/Makefile.am index 976e73050..84da9a9d3 100644 --- a/sys/v4l2/Makefile.am +++ b/sys/v4l2/Makefile.am @@ -4,7 +4,7 @@ plugin_LTLIBRARIES = \ libgstv4l2element.la \ libgstv4l2src.la -libgstv4l2element_la_SOURCES = gstv4l2element.c v4l2_calls.c v4l2-overlay_calls.c +libgstv4l2element_la_SOURCES = gstv4l2element.c v4l2_calls.c v4l2-overlay_calls.c gstv4l2element-marshal.c libgstv4l2element_la_CFLAGS = $(GST_CFLAGS) libgstv4l2element_la_LIBADD = libgstv4l2element_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) @@ -15,4 +15,32 @@ libgstv4l2src_la_LIBADD = libgstv4l2element.la libgstv4l2src_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) noinst_HEADERS = gstv4l2element.h v4l2_calls.h \ - gstv4l2src.h v4l2src_calls.h + gstv4l2src.h v4l2src_calls.h gstv4l2element-marshal.h + +EXTRA_libgstv4l2element_la_SOURCES = \ + gstv4l2element-marshal.list + +BUILT_SOURCES = \ + gstv4l2element-marshal.c \ + gstv4l2element-marshal.h + +gstv4l2element-marshal.h: gstv4l2element-marshal.list + glib-genmarshal --header --prefix=gstv4l2_cclosure_marshal $(srcdir)/gstv4l2element-marshal.list > gstv4l2element-marshal.h.tmp + mv gstv4l2element-marshal.h.tmp gstv4l2element-marshal.h + +gstv4l2element-marshal.c: gstv4l2element-marshal.list + echo "#include \"glib.h\"" > gstv4l2element-marshal.c.tmp + echo "#include \"glib-object.h\"" >> gstv4l2element-marshal.c.tmp + echo "#include \"gstv4l2element-marshal.h\"" >> gstv4l2element-marshal.c.tmp + glib-genmarshal --body --prefix=gstv4l2_cclosure_marshal $(srcdir)/gstv4l2element-marshal.list >> gstv4l2element-marshal.c.tmp + mv gstv4l2element-marshal.c.tmp gstv4l2element-marshal.c + +# Don't want the generated marshal files in the dist +dist-hook: + rm -f $(distdir)/gstv4l2element-marshal.c + rm -f $(distdir)/gstv4l2element-marshal.h + +# Clean generated files +distclean-local: + rm -f $(top_builddir)/src/element/gstv4l2element-marshal.c + rm -f $(top_builddir)/src/element/gstv4l2element-marshal.h diff --git a/sys/v4l2/gstv4l2element-marshal.list b/sys/v4l2/gstv4l2element-marshal.list new file mode 100644 index 000000000..432112121 --- /dev/null +++ b/sys/v4l2/gstv4l2element-marshal.list @@ -0,0 +1,3 @@ +BOOLEAN:INT,INT,INT,INT,POINTER,INT +BOOLEAN:STRING,INT +BOOLEAN:STRING,POINTER diff --git a/sys/v4l2/gstv4l2element.c b/sys/v4l2/gstv4l2element.c index edff15b16..926e4a510 100644 --- a/sys/v4l2/gstv4l2element.c +++ b/sys/v4l2/gstv4l2element.c @@ -22,6 +22,7 @@ #endif #include "v4l2_calls.h" +#include "gstv4l2element-marshal.h" /* elementfactory details */ static GstElementDetails gst_v4l2element_details = { @@ -39,6 +40,9 @@ enum { /* FILL ME */ SIGNAL_OPEN, SIGNAL_CLOSE, + SIGNAL_SET_VIDEOWINDOW, + SIGNAL_GET_ATTRIBUTE, + SIGNAL_SET_ATTRIBUTE, LAST_SIGNAL }; @@ -54,15 +58,13 @@ enum { ARG_FREQUENCY, ARG_SIGNAL_STRENGTH, ARG_HAS_AUDIO, - ARG_ATTRIBUTE, - ARG_ATTRIBUTE_SETS, + ARG_ATTRIBUTES, ARG_DEVICE, ARG_DEVICE_NAME, ARG_DEVICE_HAS_CAPTURE, ARG_DEVICE_HAS_OVERLAY, ARG_DEVICE_HAS_PLAYBACK, ARG_DISPLAY, - ARG_VIDEOWINDOW, ARG_DO_OVERLAY, }; @@ -153,11 +155,8 @@ gst_v4l2element_class_init (GstV4l2ElementClass *klass) g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HAS_AUDIO, g_param_spec_boolean("has_audio","has_audio","has_audio", 0,G_PARAM_READABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ATTRIBUTE, - g_param_spec_pointer("attribute","attribute","attribute", - G_PARAM_READWRITE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ATTRIBUTE_SETS, - g_param_spec_pointer("attribute_sets","attribute_sets","attribute_sets", + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ATTRIBUTES, + g_param_spec_pointer("attributes","attributes","attributes", G_PARAM_READABLE)); g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE, @@ -183,9 +182,37 @@ gst_v4l2element_class_init (GstV4l2ElementClass *klass) g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DO_OVERLAY, g_param_spec_boolean("do_overlay","do_overlay","do_overlay", 0,G_PARAM_WRITABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VIDEOWINDOW, - g_param_spec_pointer("videowindow","videowindow","videowindow", - G_PARAM_WRITABLE)); + + /* actions */ + gst_v4l2element_signals[SIGNAL_SET_VIDEOWINDOW] = + g_signal_new ("set_videowindow", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(GstV4l2ElementClass, set_videowindow), + NULL, NULL, + gstv4l2_cclosure_marshal_BOOLEAN__INT_INT_INT_INT_POINTER_INT, + G_TYPE_BOOLEAN, 6, + G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, + G_TYPE_POINTER, G_TYPE_INT); + klass->set_videowindow = gst_v4l2_set_window; + gst_v4l2element_signals[SIGNAL_GET_ATTRIBUTE] = + g_signal_new ("get_attribute", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(GstV4l2ElementClass, get_attribute), + NULL, NULL, + gstv4l2_cclosure_marshal_BOOLEAN__STRING_POINTER, + G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_POINTER); + klass->get_attribute = gst_v4l2_get_attribute; + gst_v4l2element_signals[SIGNAL_SET_ATTRIBUTE] = + g_signal_new ("set_attribute", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(GstV4l2ElementClass, set_attribute), + NULL, NULL, + gstv4l2_cclosure_marshal_BOOLEAN__STRING_INT, + G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_INT); + klass->set_attribute = gst_v4l2_set_attribute; /* signals */ gst_v4l2element_signals[SIGNAL_OPEN] = @@ -220,9 +247,14 @@ gst_v4l2element_init (GstV4l2Element *v4l2element) v4l2element->frequency = 0; v4l2element->controls = NULL; + v4l2element->menus = NULL; + v4l2element->control_specs = NULL; v4l2element->outputs = NULL; + v4l2element->output_names = NULL; v4l2element->inputs = NULL; + v4l2element->input_names = NULL; v4l2element->norms = NULL; + v4l2element->norm_names = NULL; } @@ -267,13 +299,6 @@ gst_v4l2element_set_property (GObject *object, return; } break; - case ARG_ATTRIBUTE: - if (GST_V4L2_IS_OPEN(v4l2element)) { - gst_v4l2_set_attribute(v4l2element, - ((GstV4l2Attribute*)g_value_get_pointer(value))->index, - ((GstV4l2Attribute*)g_value_get_pointer(value))->value); - } - break; case ARG_DEVICE: if (!GST_V4L2_IS_OPEN(v4l2element)) { if (v4l2element->device) @@ -285,15 +310,6 @@ gst_v4l2element_set_property (GObject *object, if (!gst_v4l2_set_display(v4l2element, g_value_get_string(value))) return; break; - case ARG_VIDEOWINDOW: - if (GST_V4L2_IS_OPEN(v4l2element)) { - GByteArray *array = (GByteArray *) g_value_get_pointer(value); - struct v4l2_clip *clips = (struct v4l2_clip *) array->data; - gst_v4l2_set_window(v4l2element, - clips->c.left, clips->c.top, clips->c.width, clips->c.height, - &clips[1], array->len/sizeof(struct v4l2_clip)-1); - } - break; case ARG_DO_OVERLAY: if (GST_V4L2_IS_OPEN(v4l2element)) { if (!gst_v4l2_enable_overlay(v4l2element, g_value_get_boolean(value))) @@ -316,7 +332,6 @@ gst_v4l2element_get_property (GObject *object, GstV4l2Element *v4l2element; gint temp_i = 0; gulong temp_ul = 0; - GList *list = NULL; /* it's not null if we got it, but it might not be ours */ g_return_if_fail(GST_IS_V4L2ELEMENT(object)); @@ -329,9 +344,7 @@ gst_v4l2element_get_property (GObject *object, g_value_set_int(value, temp_i); break; case ARG_CHANNEL_NAMES: - if (GST_V4L2_IS_OPEN(v4l2element)) - list = gst_v4l2_get_input_names(v4l2element); - g_value_set_pointer(value, list); + g_value_set_pointer(value, v4l2element->input_names); break; case ARG_OUTPUT: if (GST_V4L2_IS_OPEN(v4l2element)) @@ -339,9 +352,7 @@ gst_v4l2element_get_property (GObject *object, g_value_set_int(value, temp_i); break; case ARG_OUTPUT_NAMES: - if (GST_V4L2_IS_OPEN(v4l2element)) - list = gst_v4l2_get_output_names(v4l2element); - g_value_set_pointer(value, list); + g_value_set_pointer(value, v4l2element->output_names); break; case ARG_NORM: if (GST_V4L2_IS_OPEN(v4l2element)) @@ -349,9 +360,7 @@ gst_v4l2element_get_property (GObject *object, g_value_set_int(value, temp_i); break; case ARG_NORM_NAMES: - if (GST_V4L2_IS_OPEN(v4l2element)) - list = gst_v4l2_get_norm_names(v4l2element); - g_value_set_pointer(value, list); + g_value_set_pointer(value, v4l2element->norm_names); break; case ARG_HAS_TUNER: if (GST_V4L2_IS_OPEN(v4l2element)) @@ -373,23 +382,15 @@ gst_v4l2element_get_property (GObject *object, temp_i = gst_v4l2_has_audio(v4l2element); g_value_set_boolean(value, temp_i>0?TRUE:FALSE); break; - case ARG_ATTRIBUTE: - if (GST_V4L2_IS_OPEN(v4l2element)) - gst_v4l2_get_attribute(v4l2element, - ((GstV4l2Attribute*)g_value_get_pointer(value))->index, &temp_i); - ((GstV4l2Attribute*)g_value_get_pointer(value))->value = temp_i; - break; - case ARG_ATTRIBUTE_SETS: - if (GST_V4L2_IS_OPEN(v4l2element)) - list = gst_v4l2_get_attributes(v4l2element); - g_value_set_pointer(value, list); + case ARG_ATTRIBUTES: + g_value_set_pointer(value, v4l2element->control_specs); break; case ARG_DEVICE: - g_value_set_string(value, g_strdup(v4l2element->device)); + g_value_set_string(value, v4l2element->device); break; case ARG_DEVICE_NAME: if (GST_V4L2_IS_OPEN(v4l2element)) - g_value_set_string(value, g_strdup(v4l2element->vcap.card)); + g_value_set_string(value, v4l2element->vcap.card); break; case ARG_DEVICE_HAS_CAPTURE: if (GST_V4L2_IS_OPEN(v4l2element) && diff --git a/sys/v4l2/gstv4l2element.h b/sys/v4l2/gstv4l2element.h index 87ebaad98..0e4620368 100644 --- a/sys/v4l2/gstv4l2element.h +++ b/sys/v4l2/gstv4l2element.h @@ -41,28 +41,6 @@ typedef struct _GstV4l2Element GstV4l2Element; typedef struct _GstV4l2ElementClass GstV4l2ElementClass; -typedef enum { - GST_V4L2_ATTRIBUTE_VALUE_TYPE_INTEGER = V4L2_CTRL_TYPE_INTEGER, - GST_V4L2_ATTRIBUTE_VALUE_TYPE_BOOLEAN = V4L2_CTRL_TYPE_BOOLEAN, - GST_V4L2_ATTRIBUTE_VALUE_TYPE_MENU = V4L2_CTRL_TYPE_MENU, - GST_V4L2_ATTRIBUTE_VALUE_TYPE_BUTTON = V4L2_CTRL_TYPE_BUTTON, -} GstV4l2AttributeValueType; - -typedef enum { - GST_V4L2_ATTRIBUTE_TYPE_VIDEO, - GST_V4L2_ATTRIBUTE_TYPE_AUDIO, - GST_V4L2_ATTRIBUTE_TYPE_OTHER, -} GstV4l2AttributeType; - -typedef struct _GstV4l2Attribute { - gint index; - gchar *name; - GstV4l2AttributeType type; - GstV4l2AttributeValueType val_type; - gint min, max, value; - GList *list_items; /* in case of 'list' */ -} GstV4l2Attribute; - struct _GstV4l2Element { GstElement element; @@ -79,10 +57,10 @@ struct _GstV4l2Element { struct v4l2_capability vcap; /* the toys available to us */ - GList /*v4l2_input*/ *inputs; - GList /*v4l2_output*/ *outputs; - GList /*v4l2_enumstd*/ *norms; - GList /*v4l2_queryctrl*/ *controls; + GList /*v4l2_input*/ *inputs, *input_names; + GList /*v4l2_output*/ *outputs, *output_names; + GList /*v4l2_enumstd*/ *norms, *norm_names; + GList /*v4l2_queryctrl*/ *controls, *control_specs; GList /*GList:v4l2_querymenu*/ *menus; /* caching values */ @@ -96,10 +74,25 @@ struct _GstV4l2ElementClass { GstElementClass parent_class; /* signals */ - void (*open) (GstElement *element, - const gchar *device); - void (*close) (GstElement *element, - const gchar *device); + void (*open) (GstElement *element, + const gchar *device); + void (*close) (GstElement *element, + const gchar *device); + + /* actions */ + gboolean (*set_videowindow) (GstElement *element, + gint x_offset, + gint y_offset, + gint height, + gint width, + struct v4l2_clip *clips, + gint num_clips); + gboolean (*get_attribute) (GstElement *element, + const gchar *attr_name, + int *value); + gboolean (*set_attribute) (GstElement *element, + const gchar *attr_name, + const int value); }; diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index c84993aa6..3dc6c9a0f 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -45,8 +45,6 @@ enum { ARG_HEIGHT, ARG_PALETTE, ARG_PALETTE_NAMES, - ARG_FOURCC, - ARG_FOURCC_LIST, ARG_NUMBUFS, ARG_BUFSIZE }; @@ -154,12 +152,6 @@ gst_v4l2src_class_init (GstV4l2SrcClass *klass) g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PALETTE_NAMES, g_param_spec_pointer("palette_name","palette_name","palette_name", G_PARAM_READABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FOURCC, - g_param_spec_string("fourcc","fourcc","fourcc", - NULL,G_PARAM_READWRITE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FOURCC_LIST, - g_param_spec_pointer("fourcc_list","fourcc_list","fourcc_list", - G_PARAM_READABLE)); g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NUMBUFS, g_param_spec_int("num_buffers","num_buffers","num_buffers", @@ -201,6 +193,7 @@ gst_v4l2src_init (GstV4l2Src *v4l2src) v4l2src->breq.count = 0; v4l2src->formats = NULL; + v4l2src->format_list = NULL; } @@ -742,19 +735,6 @@ gst_v4l2src_set_property (GObject *object, } break; - case ARG_FOURCC: - if (!GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src))) { - gint i; - const gchar *formatstr = g_value_get_string(value); - guint32 fourcc = GST_MAKE_FOURCC(formatstr[0],formatstr[1],formatstr[2],formatstr[3]); - for (i=0;i<g_list_length(v4l2src->formats);i++) { - struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, i); - if (fmt->pixelformat == fourcc) - v4l2src->palette = i; - } - } - break; - case ARG_NUMBUFS: if (!GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src))) { v4l2src->breq.count = g_value_get_int(value); @@ -793,18 +773,7 @@ gst_v4l2src_get_property (GObject *object, break; case ARG_PALETTE_NAMES: - g_value_set_pointer(value, gst_v4l2src_get_format_list(v4l2src)); - break; - - case ARG_FOURCC: { - struct v4l2_fmtdesc *fmt = g_list_nth_data(v4l2src->formats, v4l2src->palette); - guint32 print_format = GUINT32_FROM_LE(fmt->pixelformat); - gchar *print_format_str = (gchar *) &print_format; - g_value_set_string(value, g_strndup(print_format_str, 4)); - break; } - - case ARG_FOURCC_LIST: - g_value_set_pointer(value, gst_v4l2src_get_fourcc_list(v4l2src)); + g_value_set_pointer(value, v4l2src->format_list); break; case ARG_NUMBUFS: diff --git a/sys/v4l2/gstv4l2src.h b/sys/v4l2/gstv4l2src.h index d287076b7..401161c7a 100644 --- a/sys/v4l2/gstv4l2src.h +++ b/sys/v4l2/gstv4l2src.h @@ -45,7 +45,7 @@ struct _GstV4l2Src { GstPad *srcpad; /* internal lists */ - GList /*v4l2_fmtdesc*/ *formats; /* list of available capture formats */ + GList /*v4l2_fmtdesc*/ *formats, *format_list; /* list of available capture formats */ /* buffer properties */ struct v4l2_buffer bufsettings; diff --git a/sys/v4l2/v4l2-overlay_calls.c b/sys/v4l2/v4l2-overlay_calls.c index ad3ec78ae..a78cdc681 100644 --- a/sys/v4l2/v4l2-overlay_calls.c +++ b/sys/v4l2/v4l2-overlay_calls.c @@ -81,7 +81,7 @@ gst_v4l2_set_display (GstV4l2Element *v4l2element, ******************************************************/ gboolean -gst_v4l2_set_window (GstV4l2Element *v4l2element, +gst_v4l2_set_window (GstElement *element, gint x, gint y, gint w, @@ -90,6 +90,7 @@ gst_v4l2_set_window (GstV4l2Element *v4l2element, gint num_clips) { struct v4l2_format fmt; + GstV4l2Element *v4l2element = GST_V4L2ELEMENT(element); DEBUG("trying to set video window to %dx%d,%d,%d", x,y,w,h); GST_V4L2_CHECK_OVERLAY(v4l2element); diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c index cb108416d..24d257445 100644 --- a/sys/v4l2/v4l2_calls.c +++ b/sys/v4l2/v4l2_calls.c @@ -90,6 +90,8 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element) inpptr = g_malloc(sizeof(input)); memcpy(inpptr, &input, sizeof(input)); v4l2element->inputs = g_list_append(v4l2element->inputs, inpptr); + + v4l2element->input_names = g_list_append(v4l2element->input_names, inpptr->name); } /* outputs */ @@ -109,6 +111,8 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element) outptr = g_malloc(sizeof(output)); memcpy(outptr, &output, sizeof(output)); v4l2element->outputs = g_list_append(v4l2element->outputs, outptr); + + v4l2element->output_names = g_list_append(v4l2element->output_names, outptr->name); } /* norms... */ @@ -128,12 +132,15 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element) stdptr = g_malloc(sizeof(standard)); memcpy(stdptr, &standard, sizeof(standard)); v4l2element->norms = g_list_append(v4l2element->norms, stdptr); + + v4l2element->norm_names = g_list_append(v4l2element->norm_names, stdptr->name); } /* and lastly, controls+menus (if appropriate) */ for (n=V4L2_CID_BASE;;n++) { struct v4l2_queryctrl control, *ctrlptr; GList *menus = NULL; + GParamSpec *spec = NULL; /* hacky... */ if (n == V4L2_CID_LASTP1) n = V4L2_CID_PRIVATE_BASE; @@ -178,6 +185,30 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element) } } v4l2element->menus = g_list_append(v4l2element->menus, menus); + + switch (control.type) { + case V4L2_CTRL_TYPE_INTEGER: + spec = g_param_spec_int(ctrlptr->name, ctrlptr->name, + ctrlptr->name, ctrlptr->minimum, ctrlptr->maximum, + ctrlptr->default_value, G_PARAM_READWRITE); + break; + case V4L2_CTRL_TYPE_BOOLEAN: + spec = g_param_spec_boolean(ctrlptr->name, ctrlptr->name, + ctrlptr->name, ctrlptr->default_value, + G_PARAM_READWRITE); + break; + case V4L2_CTRL_TYPE_MENU: + /* hacky... we abuse pointer for 'no value' */ + spec = g_param_spec_pointer(ctrlptr->name, ctrlptr->name, + ctrlptr->name, G_PARAM_WRITABLE); + break; + case V4L2_CTRL_TYPE_BUTTON: + /* help?!? */ + spec = NULL; + break; + } + + v4l2element->control_specs = g_list_append(v4l2element->control_specs, spec); } return TRUE; @@ -195,16 +226,22 @@ gst_v4l2_empty_lists (GstV4l2Element *v4l2element) v4l2element->inputs = g_list_remove(v4l2element->inputs, data); g_free(data); } + g_list_free(v4l2element->input_names); + v4l2element->input_names = NULL; while (g_list_length(v4l2element->outputs) > 0) { gpointer data = g_list_nth_data(v4l2element->outputs, 0); v4l2element->outputs = g_list_remove(v4l2element->outputs, data); g_free(data); } + g_list_free(v4l2element->output_names); + v4l2element->output_names = NULL; while (g_list_length(v4l2element->norms) > 0) { gpointer data = g_list_nth_data(v4l2element->norms, 0); v4l2element->norms = g_list_remove(v4l2element->norms, data); g_free(data); } + g_list_free(v4l2element->norm_names); + v4l2element->norm_names = NULL; while (g_list_length(v4l2element->controls) > 0) { gpointer data = g_list_nth_data(v4l2element->controls, 0); v4l2element->controls = g_list_remove(v4l2element->controls, data); @@ -220,6 +257,11 @@ gst_v4l2_empty_lists (GstV4l2Element *v4l2element) g_free(data); } } + while (g_list_length(v4l2element->control_specs) > 0) { + gpointer data = g_list_nth_data(v4l2element->control_specs, 0); + v4l2element->control_specs = g_list_remove(v4l2element->control_specs, data); + g_param_spec_unref(G_PARAM_SPEC(data)); + } } @@ -376,29 +418,6 @@ gst_v4l2_set_norm (GstV4l2Element *v4l2element, /****************************************************** - * gst_v4l2_get_norm_names() - * Get the list of available norms - * return value: the list - ******************************************************/ - -GList * -gst_v4l2_get_norm_names (GstV4l2Element *v4l2element) -{ - GList *names = NULL; - gint n; - - DEBUG("getting a list of norm names"); - - for (n=0;n<g_list_length(v4l2element->norms);n++) { - struct v4l2_standard *standard = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, n); - names = g_list_append(names, g_strdup(standard->name)); - } - - return names; -} - - -/****************************************************** * gst_v4l2_get_input() * Get the input of the current device * return value: TRUE on success, FALSE on error @@ -459,29 +478,6 @@ gst_v4l2_set_input (GstV4l2Element *v4l2element, /****************************************************** - * gst_v4l2_get_input_names() - * Get the list of available input channels - * return value: the list - ******************************************************/ - -GList * -gst_v4l2_get_input_names (GstV4l2Element *v4l2element) -{ - GList *names = NULL; - gint n; - - DEBUG("getting a list of input names"); - - for (n=0;n<g_list_length(v4l2element->inputs);n++) { - struct v4l2_input *input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, n); - names = g_list_append(names, g_strdup(input->name)); - } - - return names; -} - - -/****************************************************** * gst_v4l2_get_output() * Get the output of the current device * return value: TRUE on success, FALSE on error @@ -542,30 +538,7 @@ gst_v4l2_set_output (GstV4l2Element *v4l2element, /****************************************************** - * gst_v4l2_get_output_names() - * Get the list of available output channels - * return value: the list, or NULL on error - ******************************************************/ - -GList * -gst_v4l2_get_output_names (GstV4l2Element *v4l2element) -{ - GList *names = NULL; - gint n; - - DEBUG("getting a list of output names"); - - for (n=0;n<g_list_length(v4l2element->outputs);n++) { - struct v4l2_output *output = (struct v4l2_output *) g_list_nth_data(v4l2element->outputs, n); - names = g_list_append(names, g_strdup(output->name)); - } - - return names; -} - - -/****************************************************** - * gst_v4l_has_tuner(): + * gst_v4l2_has_tuner(): * Check whether the device has a tuner * return value: TRUE if it has a tuner, else FALSE ******************************************************/ @@ -595,7 +568,7 @@ gst_v4l2_has_tuner (GstV4l2Element *v4l2element, /****************************************************** - * gst_v4l_get_frequency(): + * gst_v4l2_get_frequency(): * get the current frequency * return value: TRUE on success, FALSE on error ******************************************************/ @@ -628,7 +601,7 @@ gst_v4l2_get_frequency (GstV4l2Element *v4l2element, /****************************************************** - * gst_v4l_set_frequency(): + * gst_v4l2_set_frequency(): * set frequency * return value: TRUE on success, FALSE on error ******************************************************/ @@ -661,7 +634,7 @@ gst_v4l2_set_frequency (GstV4l2Element *v4l2element, /****************************************************** - * gst_v4l_signal_strength(): + * gst_v4l2_signal_strength(): * get the strength of the signal on the current input * return value: TRUE on success, FALSE on error ******************************************************/ @@ -689,7 +662,7 @@ gst_v4l2_signal_strength (GstV4l2Element *v4l2element, /****************************************************** - * gst_v4l_has_audio(): + * gst_v4l2_has_audio(): * Check whether the device has audio capabilities * return value: TRUE if it has a tuner, else FALSE ******************************************************/ @@ -713,96 +686,53 @@ gst_v4l2_has_audio (GstV4l2Element *v4l2element) /****************************************************** - * gst_v4l_get_attributes(): - * get a list of attributes available on this device - * return value: the list + * gst_v4l2_control_name_to_num(): + * convert name to num (-1 if nothing) ******************************************************/ -GList * -gst_v4l2_get_attributes (GstV4l2Element *v4l2element) +static gint +gst_v4l2_control_name_to_num (GstV4l2Element *v4l2element, + const gchar *name) { - gint i; - GList *list = NULL; - - DEBUG("getting a list of available attributes"); - - for (i=0;i<g_list_length(v4l2element->controls);i++) { - struct v4l2_queryctrl *control = (struct v4l2_queryctrl *) g_list_nth_data(v4l2element->controls, i); - GstV4l2Attribute* attribute = g_malloc(sizeof(GstV4l2Attribute)); - attribute->name = g_strdup(control->name); - attribute->index = i; - attribute->list_items = NULL; - attribute->val_type = control->type; - if (control->type == V4L2_CTRL_TYPE_MENU) { - /* list items */ - gint n; - GList *menus = (GList *) g_list_nth_data(v4l2element->menus, i); - for (n=0;n<g_list_length(menus);n++) { - struct v4l2_querymenu *menu = g_list_nth_data(menus, n); - attribute->list_items = g_list_append(attribute->list_items, - g_strdup(menu->name)); - } - } - switch (control->id) { - case V4L2_CID_BRIGHTNESS: - case V4L2_CID_CONTRAST: - case V4L2_CID_SATURATION: - case V4L2_CID_HUE: - case V4L2_CID_BLACK_LEVEL: - case V4L2_CID_AUTO_WHITE_BALANCE: - case V4L2_CID_DO_WHITE_BALANCE: - case V4L2_CID_RED_BALANCE: - case V4L2_CID_BLUE_BALANCE: - case V4L2_CID_GAMMA: - case V4L2_CID_EXPOSURE: - case V4L2_CID_AUTOGAIN: - case V4L2_CID_GAIN: - case V4L2_CID_HFLIP: - case V4L2_CID_VFLIP: - case V4L2_CID_HCENTER: - case V4L2_CID_VCENTER: - attribute->type = GST_V4L2_ATTRIBUTE_TYPE_VIDEO; - break; - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - case V4L2_CID_AUDIO_MUTE: - case V4L2_CID_AUDIO_LOUDNESS: - attribute->type = GST_V4L2_ATTRIBUTE_TYPE_AUDIO; - break; - default: - attribute->type = GST_V4L2_ATTRIBUTE_TYPE_OTHER; - break; - } - gst_v4l2_get_attribute(v4l2element, i, &attribute->value); - attribute->min = control->minimum; - attribute->max = control->maximum; + GList *item; + + for (item = v4l2element->controls; item != NULL; item = item->next) { + struct v4l2_queryctrl *ctrl = item->data; + if (!strcmp(ctrl->name, name)) + return ctrl->id; } - return list; + return -1; } /****************************************************** - * gst_v4l_get_attribute(): + * gst_v4l2_get_attribute(): * try to get the value of one specific attribute * return value: TRUE on success, FALSE on error ******************************************************/ gboolean -gst_v4l2_get_attribute (GstV4l2Element *v4l2element, - gint attribute_num, - gint *value) +gst_v4l2_get_attribute (GstElement *element, + const gchar *name, + int *value) { struct v4l2_control control; + GstV4l2Element *v4l2element; + gint attribute_num = -1; + + g_return_val_if_fail(element != NULL && name != NULL && value != NULL, FALSE); + g_return_val_if_fail(GST_IS_V4L2ELEMENT(element), FALSE); + v4l2element = GST_V4L2ELEMENT(element); DEBUG("getting value of attribute %d", attribute_num); GST_V4L2_CHECK_OPEN(v4l2element); - if (attribute_num < 0 || attribute_num >= g_list_length(v4l2element->controls)) { + attribute_num = gst_v4l2_control_name_to_num(v4l2element, name); + + if (attribute_num < 0) { gst_element_error(GST_ELEMENT(v4l2element), - "Invalid control ID %d", attribute_num); + "Invalid control %s", name); return FALSE; } @@ -810,8 +740,8 @@ gst_v4l2_get_attribute (GstV4l2Element *v4l2element, if (ioctl(v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) { gst_element_error(GST_ELEMENT(v4l2element), - "Failed to get value for control %d on device %s: %s", - attribute_num, v4l2element->device, g_strerror(errno)); + "Failed to get value for control %s (%d) on device %s: %s", + name, attribute_num, v4l2element->device, g_strerror(errno)); return FALSE; } @@ -822,24 +752,32 @@ gst_v4l2_get_attribute (GstV4l2Element *v4l2element, /****************************************************** - * gst_v4l_set_attribute(): + * gst_v4l2_set_attribute(): * try to set the value of one specific attribute * return value: TRUE on success, FALSE on error ******************************************************/ gboolean -gst_v4l2_set_attribute (GstV4l2Element *v4l2element, - gint attribute_num, - gint value) +gst_v4l2_set_attribute (GstElement *element, + const gchar *name, + const int value) { struct v4l2_control control; + GstV4l2Element *v4l2element; + gint attribute_num = -1; + + g_return_val_if_fail(element != NULL && name != NULL, FALSE); + g_return_val_if_fail(GST_IS_V4L2ELEMENT(element), FALSE); + v4l2element = GST_V4L2ELEMENT(element); DEBUG("setting value of attribute %d to %d", attribute_num, value); GST_V4L2_CHECK_OPEN(v4l2element); - if (attribute_num < 0 || attribute_num >= g_list_length(v4l2element->controls)) { + attribute_num = gst_v4l2_control_name_to_num(v4l2element, name); + + if (attribute_num < 0) { gst_element_error(GST_ELEMENT(v4l2element), - "Invalid control ID %d", attribute_num); + "Invalid control %s", name); return FALSE; } @@ -848,8 +786,8 @@ gst_v4l2_set_attribute (GstV4l2Element *v4l2element, if (ioctl(v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) { gst_element_error(GST_ELEMENT(v4l2element), - "Failed to set value %d for control %d on device %s: %s", - value, attribute_num, v4l2element->device, g_strerror(errno)); + "Failed to set value %d for control %s (%d) on device %s: %s", + value, name, attribute_num, v4l2element->device, g_strerror(errno)); return FALSE; } diff --git a/sys/v4l2/v4l2_calls.h b/sys/v4l2/v4l2_calls.h index db9adc08e..e03c7abe5 100644 --- a/sys/v4l2/v4l2_calls.h +++ b/sys/v4l2/v4l2_calls.h @@ -89,17 +89,14 @@ gboolean gst_v4l2_get_norm (GstV4l2Element *v4l2element, gint *norm); gboolean gst_v4l2_set_norm (GstV4l2Element *v4l2element, gint norm); -GList * gst_v4l2_get_norm_names (GstV4l2Element *v4l2element); gboolean gst_v4l2_get_input (GstV4l2Element *v4l2element, gint *input); gboolean gst_v4l2_set_input (GstV4l2Element *v4l2element, gint input); -GList * gst_v4l2_get_input_names (GstV4l2Element *v4l2element); gboolean gst_v4l2_get_output (GstV4l2Element *v4l2element, gint *output); gboolean gst_v4l2_set_output (GstV4l2Element *v4l2element, gint output); -GList * gst_v4l2_get_output_names (GstV4l2Element *v4l2element); /* frequency control */ gboolean gst_v4l2_has_tuner (GstV4l2Element *v4l2element, @@ -113,18 +110,17 @@ gboolean gst_v4l2_signal_strength (GstV4l2Element *v4l2element, /* attribute control */ gboolean gst_v4l2_has_audio (GstV4l2Element *v4l2element); -GList * gst_v4l2_get_attributes (GstV4l2Element *v4l2element); -gboolean gst_v4l2_get_attribute (GstV4l2Element *v4l2element, - gint attribute_num, - gint *value); -gboolean gst_v4l2_set_attribute (GstV4l2Element *v4l2element, - gint attribute_num, - gint value); +gboolean gst_v4l2_get_attribute (GstElement *element, + const char *attribute, + int *value); +gboolean gst_v4l2_set_attribute (GstElement *element, + const char *attribute, + const int value); /* overlay */ gboolean gst_v4l2_set_display (GstV4l2Element *v4l2element, const gchar *display); -gboolean gst_v4l2_set_window (GstV4l2Element *v4l2element, +gboolean gst_v4l2_set_window (GstElement *element, gint x, gint y, gint w, gint h, struct v4l2_clip *clips, diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c index a6f244fea..d6c9655f9 100644 --- a/sys/v4l2/v4l2src_calls.c +++ b/sys/v4l2/v4l2src_calls.c @@ -72,6 +72,8 @@ gst_v4l2src_fill_format_list (GstV4l2Src *v4l2src) fmtptr = g_malloc(sizeof(format)); memcpy(fmtptr, &format, sizeof(format)); v4l2src->formats = g_list_append(v4l2src->formats, fmtptr); + + v4l2src->format_list = g_list_append(v4l2src->format_list, fmtptr->description); } return TRUE; @@ -92,6 +94,8 @@ gst_v4l2src_empty_format_list (GstV4l2Src *v4l2src) v4l2src->formats = g_list_remove(v4l2src->formats, data); g_free(data); } + g_list_free(v4l2src->format_list); + v4l2src->format_list = NULL; return TRUE; } @@ -399,49 +403,3 @@ gst_v4l2src_capture_deinit (GstV4l2Src *v4l2src) return TRUE; } - - -/****************************************************** - * gst_v4l2src_get_fourcc_list(): - * create a list of all available fourccs - * return value: the list - ******************************************************/ - -GList * -gst_v4l2src_get_fourcc_list (GstV4l2Src *v4l2src) -{ - GList *list = NULL; - gint n; - - for (n=0;n<g_list_length(v4l2src->formats);n++) { - struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, n); - guint32 print_format = GUINT32_FROM_LE(fmt->pixelformat); - gchar *print_format_str = (gchar *) &print_format; - - list = g_list_append(list, g_strndup(print_format_str, 4)); - } - - return list; -} - - -/****************************************************** - * gst_v4l2src_get_format_list(): - * create a list of all available capture formats - * return value: the list - ******************************************************/ - -GList * -gst_v4l2src_get_format_list (GstV4l2Src *v4l2src) -{ - GList *list = NULL; - gint n; - - for (n=0;n<g_list_length(v4l2src->formats);n++) { - struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, n); - - list = g_list_append(list, g_strdup(fmt->description)); - } - - return list; -} diff --git a/sys/v4l2/v4l2src_calls.h b/sys/v4l2/v4l2src_calls.h index 436f65dcc..263d89a3c 100644 --- a/sys/v4l2/v4l2src_calls.h +++ b/sys/v4l2/v4l2src_calls.h @@ -40,8 +40,6 @@ gboolean gst_v4l2src_capture_deinit (GstV4l2Src *v4l2src); gboolean gst_v4l2src_fill_format_list (GstV4l2Src *v4l2src); gboolean gst_v4l2src_empty_format_list (GstV4l2Src *v4l2src); -GList * gst_v4l2src_get_fourcc_list (GstV4l2Src *v4l2src); -GList * gst_v4l2src_get_format_list (GstV4l2Src *v4l2src); #endif /* __V4L2_SRC_CALLS_H__ */ |