v4l plugins: add open/close signals v4l2 plugins: add open/close signals move source...
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Wed, 13 Nov 2002 12:35:56 +0000 (12:35 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Wed, 13 Nov 2002 12:35:56 +0000 (12:35 +0000)
Original commit message from CVS:
v4l plugins:
* add open/close signals

v4l2 plugins:
* add open/close signals
* move source format enumeration from v4l2element to v4l2src
* adapt to the final v4l2 API in kernel 2.5 (patches for 2.4 on http://bytesex.org/patches)
* small tweaks

sys/v4l2/gstv4l2element.c
sys/v4l2/gstv4l2element.h
sys/v4l2/gstv4l2src.c
sys/v4l2/gstv4l2src.h
sys/v4l2/v4l2-overlay_calls.c
sys/v4l2/v4l2_calls.c
sys/v4l2/v4l2_calls.h
sys/v4l2/v4l2src_calls.c
sys/v4l2/v4l2src_calls.h

index 2c3a304..edff15b 100644 (file)
@@ -37,6 +37,8 @@ static GstElementDetails gst_v4l2element_details = {
 /* V4l2Element signals and args */
 enum {
        /* FILL ME */
+       SIGNAL_OPEN,
+       SIGNAL_CLOSE,
        LAST_SIGNAL
 };
 
@@ -58,7 +60,7 @@ enum {
        ARG_DEVICE_NAME,
        ARG_DEVICE_HAS_CAPTURE,
        ARG_DEVICE_HAS_OVERLAY,
-       ARG_DEVICE_HAS_CODEC,
+       ARG_DEVICE_HAS_PLAYBACK,
        ARG_DISPLAY,
        ARG_VIDEOWINDOW,
        ARG_DO_OVERLAY,
@@ -79,7 +81,7 @@ static GstElementStateReturn  gst_v4l2element_change_state    (GstElement          *
 
 
 static GstElementClass *parent_class = NULL;
-/*static guint gst_v4l2element_signals[LAST_SIGNAL] = { 0 }; */
+static guint gst_v4l2element_signals[LAST_SIGNAL] = { 0 };
 
 
 GType
@@ -168,12 +170,12 @@ gst_v4l2element_class_init (GstV4l2ElementClass *klass)
        g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_CAPTURE,
                g_param_spec_boolean("can_capture","can_capture","can_capture",
                0,G_PARAM_READABLE));
+       g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_PLAYBACK,
+               g_param_spec_boolean("can_playback","can_playback","can_playback",
+               0,G_PARAM_READABLE));
        g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_OVERLAY,
                g_param_spec_boolean("has_overlay","has_overlay","has_overlay",
                0,G_PARAM_READABLE));
-       g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_CODEC,
-               g_param_spec_boolean("has_compression","has_compression","has_compression",
-               0,G_PARAM_READABLE));
 
        g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DISPLAY,
                g_param_spec_string("display","display","display",
@@ -185,6 +187,18 @@ gst_v4l2element_class_init (GstV4l2ElementClass *klass)
                g_param_spec_pointer("videowindow","videowindow","videowindow",
                G_PARAM_WRITABLE));
 
+       /* signals */
+       gst_v4l2element_signals[SIGNAL_OPEN] =
+               g_signal_new("open", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
+                       G_STRUCT_OFFSET(GstV4l2ElementClass, open),
+                       NULL, NULL, g_cclosure_marshal_VOID__STRING,
+                       G_TYPE_NONE, 1, G_TYPE_STRING);
+       gst_v4l2element_signals[SIGNAL_CLOSE] =
+               g_signal_new("close", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
+                       G_STRUCT_OFFSET(GstV4l2ElementClass, close),
+                       NULL, NULL, g_cclosure_marshal_VOID__STRING,
+                       G_TYPE_NONE, 1, G_TYPE_STRING);
+
        gobject_class->set_property = gst_v4l2element_set_property;
        gobject_class->get_property = gst_v4l2element_get_property;
 
@@ -206,7 +220,6 @@ gst_v4l2element_init (GstV4l2Element *v4l2element)
        v4l2element->frequency = 0;
 
        v4l2element->controls = NULL;
-       v4l2element->formats = NULL;
        v4l2element->outputs = NULL;
        v4l2element->inputs = NULL;
        v4l2element->norms = NULL;
@@ -277,7 +290,7 @@ gst_v4l2element_set_property (GObject      *object,
                                GByteArray *array = (GByteArray *) g_value_get_pointer(value);
                                struct v4l2_clip *clips = (struct v4l2_clip *) array->data;
                                gst_v4l2_set_window(v4l2element,
-                                       clips->x, clips->y, clips->width, clips->height,
+                                       clips->c.left, clips->c.top, clips->c.width, clips->c.height,
                                        &clips[1], array->len/sizeof(struct v4l2_clip)-1);
                        }
                        break;
@@ -342,8 +355,8 @@ gst_v4l2element_get_property (GObject    *object,
                        break;
                case ARG_HAS_TUNER:
                        if (GST_V4L2_IS_OPEN(v4l2element))
-                               temp_i = gst_v4l2_has_tuner(v4l2element);
-                       g_value_set_boolean(value, temp_i>0?TRUE:FALSE);
+                               g_value_set_boolean(value,
+                                       gst_v4l2_has_tuner(v4l2element, &temp_i));
                        break;
                case ARG_FREQUENCY:
                        if (GST_V4L2_IS_OPEN(v4l2element))
@@ -376,25 +389,25 @@ gst_v4l2element_get_property (GObject    *object,
                        break;
                case ARG_DEVICE_NAME:
                        if (GST_V4L2_IS_OPEN(v4l2element))
-                               g_value_set_string(value, g_strdup(v4l2element->vcap.name));
+                               g_value_set_string(value, g_strdup(v4l2element->vcap.card));
                        break;
                case ARG_DEVICE_HAS_CAPTURE:
                        if (GST_V4L2_IS_OPEN(v4l2element) &&
-                           (v4l2element->vcap.type == V4L2_TYPE_CODEC ||
-                            v4l2element->vcap.type == V4L2_TYPE_CAPTURE) &&
-                           v4l2element->vcap.flags & V4L2_FLAG_STREAMING)
+                           v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE &&
+                           v4l2element->vcap.capabilities & V4L2_CAP_STREAMING)
                                temp_i = 1;
                        g_value_set_boolean(value, temp_i>0?TRUE:FALSE);
                        break;
                case ARG_DEVICE_HAS_OVERLAY:
                        if (GST_V4L2_IS_OPEN(v4l2element) &&
-                           v4l2element->vcap.flags & V4L2_FLAG_PREVIEW)
+                           v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
                                temp_i = 1;
                        g_value_set_boolean(value, temp_i>0?TRUE:FALSE);
                        break;
-               case ARG_DEVICE_HAS_CODEC:
+               case ARG_DEVICE_HAS_PLAYBACK:
                        if (GST_V4L2_IS_OPEN(v4l2element) &&
-                           v4l2element->vcap.type == V4L2_TYPE_CODEC)
+                           v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT &&
+                           v4l2element->vcap.capabilities & V4L2_CAP_STREAMING)
                                temp_i = 1;
                        g_value_set_boolean(value, temp_i>0?TRUE:FALSE);
                        break;
@@ -422,6 +435,11 @@ gst_v4l2element_change_state (GstElement *element)
                        if (!gst_v4l2_open(v4l2element))
                                return GST_STATE_FAILURE;
 
+                       /* emit a signal! whoopie! */
+                       g_signal_emit(G_OBJECT(v4l2element),
+                               gst_v4l2element_signals[SIGNAL_OPEN], 0,
+                               v4l2element->device);
+
                        /* now, sync options */
                        if (v4l2element->norm >= 0)
                                if (!gst_v4l2_set_norm(v4l2element, v4l2element->norm))
@@ -439,6 +457,11 @@ gst_v4l2element_change_state (GstElement *element)
                case GST_STATE_READY_TO_NULL:
                        if (!gst_v4l2_close(v4l2element))
                                return GST_STATE_FAILURE;
+
+                       /* emit yet another signal! wheehee! */
+                       g_signal_emit(G_OBJECT(v4l2element),
+                               gst_v4l2element_signals[SIGNAL_CLOSE], 0,
+                               v4l2element->device);
                        break;
        }
 
index b0e9fb7..87ebaad 100644 (file)
 typedef        struct _GstV4l2Element          GstV4l2Element;
 typedef        struct _GstV4l2ElementClass     GstV4l2ElementClass;
 
-typedef struct _GstV4l2Rect {
-       gint x, y, w, h;
-} GstV4l2Rect;
-
 typedef enum {
-       GST_V4L2_ATTRIBUTE_VALUE_TYPE_INT,
-       GST_V4L2_ATTRIBUTE_VALUE_TYPE_BOOLEAN,
-       GST_V4L2_ATTRIBUTE_VALUE_TYPE_BUTTON,
-       GST_V4L2_ATTRIBUTE_VALUE_TYPE_LIST,
+       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_EFFECT,
+       GST_V4L2_ATTRIBUTE_TYPE_OTHER,
 } GstV4l2AttributeType;
 
 typedef struct _GstV4l2Attribute {
@@ -83,7 +79,6 @@ struct _GstV4l2Element {
        struct v4l2_capability vcap;
 
        /* the toys available to us */
-       GList /*v4l2_fmtdesc*/ *formats; /* list of available capture formats */
        GList /*v4l2_input*/ *inputs;
        GList /*v4l2_output*/ *outputs;
        GList /*v4l2_enumstd*/ *norms;
@@ -99,6 +94,12 @@ struct _GstV4l2Element {
 
 struct _GstV4l2ElementClass {
        GstElementClass parent_class;
+
+       /* signals */
+       void (*open)    (GstElement  *element,
+                        const gchar *device);
+       void (*close)   (GstElement  *element,
+                        const gchar *device);
 };
 
 
index 6ba0ea0..52a677d 100644 (file)
@@ -56,6 +56,12 @@ enum {
 static void                    gst_v4l2src_class_init          (GstV4l2SrcClass *klass);
 static void                    gst_v4l2src_init                (GstV4l2Src      *v4l2src);
 
+/* signal functions */
+static void                    gst_v4l2src_open                (GstElement      *element,
+                                                                const gchar     *device);
+static void                    gst_v4l2src_close               (GstElement      *element,
+                                                                const gchar     *device);
+
 /* pad/buffer functions */
 static gboolean                        gst_v4l2src_srcconvert          (GstPad          *pad,
                                                                 GstFormat       src_format,
@@ -127,9 +133,11 @@ gst_v4l2src_class_init (GstV4l2SrcClass *klass)
 {
        GObjectClass *gobject_class;
        GstElementClass *gstelement_class;
+       GstV4l2ElementClass *v4l2_class;
 
        gobject_class = (GObjectClass*)klass;
        gstelement_class = (GstElementClass*)klass;
+       v4l2_class = (GstV4l2ElementClass*)klass;
 
        parent_class = g_type_class_ref(GST_TYPE_V4L2ELEMENT);
 
@@ -164,6 +172,9 @@ gst_v4l2src_class_init (GstV4l2SrcClass *klass)
        gobject_class->get_property = gst_v4l2src_get_property;
 
        gstelement_class->change_state = gst_v4l2src_change_state;
+
+       v4l2_class->open = gst_v4l2src_open;
+       v4l2_class->close = gst_v4l2src_close;
 }
 
 
@@ -188,6 +199,24 @@ gst_v4l2src_init (GstV4l2Src *v4l2src)
        v4l2src->width = 160;
        v4l2src->height = 120;
        v4l2src->breq.count = 0;
+
+       v4l2src->formats = NULL;
+}
+
+
+static void
+gst_v4l2src_open (GstElement  *element,
+                  const gchar *device)
+{
+       gst_v4l2src_fill_format_list(GST_V4L2SRC(element));
+}
+
+
+static void
+gst_v4l2src_close (GstElement  *element,
+                   const gchar *device)
+{
+       gst_v4l2src_empty_format_list(GST_V4L2SRC(element));
 }
 
 
@@ -211,8 +240,8 @@ gst_v4l2src_srcconvert (GstPad    *pad,
        if (!gst_v4l2_get_norm(GST_V4L2ELEMENT(v4l2src), &norm))
                return FALSE;
 
-       std = &((struct v4l2_enumstd *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->norms, norm))->std;
-       fps = std->framerate.numerator / std->framerate.denominator;
+       std = ((struct v4l2_standard *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->norms, norm));
+       fps = std->frameperiod.numerator / std->frameperiod.denominator;
 
        switch (src_format) {
                case GST_FORMAT_TIME:
@@ -453,8 +482,8 @@ gst_v4l2_caps_to_v4l2fourcc (GstV4l2Src *v4l2src,
                                        break; }
                        }
 
-                       for (i=0;i<g_list_length(GST_V4L2ELEMENT(v4l2src)->formats);i++) {
-                               struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->formats, i);
+                       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)
                                        fourcclist = g_list_append(fourcclist, (gpointer)fourcc);
                        }
@@ -585,8 +614,8 @@ gst_v4l2src_srcconnect (GstPad  *pad,
        for (i=0;i<g_list_length(fourccs);i++) {
                guint32 fourcc = (guint32)g_list_nth_data(fourccs, i);
                gint n;
-               for (n=0;n<g_list_length(v4l2element->formats);n++) {
-                       struct v4l2_fmtdesc *format = g_list_nth_data(v4l2element->formats, n);
+               for (n=0;n<g_list_length(v4l2src->formats);n++) {
+                       struct v4l2_fmtdesc *format = g_list_nth_data(v4l2src->formats, n);
                        if (format->pixelformat == fourcc) {
                                /* we found the pixelformat! - try it out */
                                if (gst_v4l2src_set_capture(v4l2src, format,
@@ -631,15 +660,15 @@ gst_v4l2src_getcaps (GstPad  *pad,
 
        /* build our own capslist */
        if (v4l2src->palette) {
-               struct v4l2_fmtdesc *format = g_list_nth_data(v4l2element->formats, v4l2src->palette);
+               struct v4l2_fmtdesc *format = g_list_nth_data(v4l2src->formats, v4l2src->palette);
                owncapslist = gst_v4l2src_v4l2fourcc_to_caps(format->pixelformat,
                                                v4l2src->width, v4l2src->height,
                                                format->flags & V4L2_FMT_FLAG_COMPRESSED);
        } else {
                gint i;
                owncapslist = NULL;
-               for (i=0;i<g_list_length(v4l2element->formats);i++) {
-                       struct v4l2_fmtdesc *format = g_list_nth_data(v4l2element->formats, i);
+               for (i=0;i<g_list_length(v4l2src->formats);i++) {
+                       struct v4l2_fmtdesc *format = g_list_nth_data(v4l2src->formats, i);
                        caps = gst_v4l2src_v4l2fourcc_to_caps(format->pixelformat,
                                                        v4l2src->width, v4l2src->height,
                                                        format->flags & V4L2_FMT_FLAG_COMPRESSED);
@@ -675,7 +704,8 @@ gst_v4l2src_get (GstPad *pad)
        GST_BUFFER_DATA(buf) = GST_V4L2ELEMENT(v4l2src)->buffer[num];
        GST_BUFFER_SIZE(buf) = v4l2src->bufsettings.bytesused;
        if (!v4l2src->first_timestamp)
-               v4l2src->first_timestamp = v4l2src->bufsettings.timestamp;
+               v4l2src->first_timestamp = v4l2src->bufsettings.timestamp.tv_sec * GST_SECOND +
+                       v4l2src->bufsettings.timestamp.tv_usec * (GST_SECOND/1000000);
        GST_BUFFER_TIMESTAMP(buf) = v4l2src->bufsettings.length - v4l2src->first_timestamp;
 
        return buf;
@@ -717,8 +747,8 @@ gst_v4l2src_set_property (GObject      *object,
                                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(GST_V4L2ELEMENT(v4l2src)->formats);i++) {
-                                       struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->formats, i);
+                               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;
                                }
@@ -767,7 +797,7 @@ gst_v4l2src_get_property (GObject    *object,
                        break;
 
                case ARG_FOURCC: {
-                       struct v4l2_fmtdesc *fmt = g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->formats, v4l2src->palette);
+                       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));
index 004347a..d287076 100644 (file)
@@ -44,11 +44,14 @@ struct _GstV4l2Src {
        /* pads */
        GstPad *srcpad;
 
+       /* internal lists */
+       GList /*v4l2_fmtdesc*/ *formats; /* list of available capture formats */
+
        /* buffer properties */
        struct v4l2_buffer bufsettings;
        struct v4l2_requestbuffers breq;
        struct v4l2_format format;
-       stamp_t first_timestamp;
+       guint64 first_timestamp;
 
        /* bufferpool for the buffers we're gonna use */
        GstBufferPool *bufferpool;
index abf1185..ad3ec78 100644 (file)
@@ -89,21 +89,23 @@ gst_v4l2_set_window (GstV4l2Element   *v4l2element,
                      struct v4l2_clip *clips,
                      gint              num_clips)
 {
-       struct v4l2_window vwin;
+       struct v4l2_format fmt;
 
        DEBUG("trying to set video window to %dx%d,%d,%d", x,y,w,h);
        GST_V4L2_CHECK_OVERLAY(v4l2element);
        GST_V4L2_CHECK_OPEN(v4l2element);
 
-       vwin.clipcount = 0;
-       vwin.x = x;
-       vwin.y = y;
-       vwin.width = w;
-       vwin.height = h;
-       vwin.clips = clips;
-       vwin.clipcount = num_clips;
-
-       if (ioctl(v4l2element->video_fd, VIDIOC_S_WIN, &vwin) < 0) {
+       fmt.type = V4L2_CAP_VIDEO_OVERLAY;
+       fmt.fmt.win.clipcount = 0;
+       fmt.fmt.win.w.left = x;
+       fmt.fmt.win.w.top = y;
+       fmt.fmt.win.w.width = w;
+       fmt.fmt.win.w.height = h;
+       fmt.fmt.win.clips = clips;
+       fmt.fmt.win.clipcount = num_clips;
+       fmt.fmt.win.bitmap = NULL;
+
+       if (ioctl(v4l2element->video_fd, VIDIOC_S_FMT, &fmt) < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
                        "Failed to set the video window on device %s: %s",
                        v4l2element->device, g_strerror(errno));
@@ -130,7 +132,7 @@ gst_v4l2_enable_overlay (GstV4l2Element *v4l2element,
        GST_V4L2_CHECK_OPEN(v4l2element);
        GST_V4L2_CHECK_OVERLAY(v4l2element);
 
-       if (ioctl(v4l2element->video_fd, VIDIOC_PREVIEW, &doit) < 0) {
+       if (ioctl(v4l2element->video_fd, VIDIOC_OVERLAY, &doit) < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
                        "Failed to %s overlay display for device %s: %s",
                        enable?"enable":"disable", v4l2element->device, g_strerror(errno));
index e09505c..cb10841 100644 (file)
@@ -73,25 +73,6 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
        DEBUG("getting enumerations");
        GST_V4L2_CHECK_OPEN(v4l2element);
 
-       /* create enumeration lists - let's start with format enumeration */
-       for (n=0;;n++) {
-               struct v4l2_fmtdesc format, *fmtptr;
-               format.index = n;
-               if (ioctl(v4l2element->video_fd, VIDIOC_ENUM_PIXFMT, &format) < 0) {
-                       if (errno == EINVAL)
-                               break; /* end of enumeration */
-                       else {
-                               gst_element_error(GST_ELEMENT(v4l2element),
-                                       "Failed to get no. %d in pixelformat enumeration for %s: %s",
-                                       n, v4l2element->device, g_strerror(errno));
-                               return FALSE;
-                       }
-               }
-               fmtptr = g_malloc(sizeof(format));
-               memcpy(fmtptr, &format, sizeof(format));
-               v4l2element->formats = g_list_append(v4l2element->formats, fmtptr);
-       }
-
        /* and now, the inputs */
        for (n=0;;n++) {
                struct v4l2_input input, *inpptr;
@@ -132,7 +113,7 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
 
        /* norms... */
        for (n=0;;n++) {
-               struct v4l2_enumstd standard, *stdptr;
+               struct v4l2_standard standard, *stdptr;
                standard.index = n;
                if (ioctl(v4l2element->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
                        if (errno == EINVAL)
@@ -150,20 +131,28 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
        }
 
        /* and lastly, controls+menus (if appropriate) */
-       for (n=0;;n++) {
+       for (n=V4L2_CID_BASE;;n++) {
                struct v4l2_queryctrl control, *ctrlptr;
                GList *menus = NULL;
+               /* hacky... */
+               if (n == V4L2_CID_LASTP1)
+                       n = V4L2_CID_PRIVATE_BASE;
                control.id = n;
                if (ioctl(v4l2element->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
-                       if (errno == EINVAL)
-                               break; /* end of enumeration */
-                       else {
+                       if (errno == EINVAL) {
+                               if (n < V4L2_CID_PRIVATE_BASE)
+                                       continue;
+                               else
+                                       break;
+                       } else {
                                gst_element_error(GST_ELEMENT(v4l2element),
                                        "Failed to get no. %d in control enumeration for %s: %s",
                                        n, v4l2element->device, g_strerror(errno));
                                return FALSE;
                        }
                }
+               if (control.flags & V4L2_CTRL_FLAG_DISABLED)
+                       continue;
                ctrlptr = g_malloc(sizeof(control));
                memcpy(ctrlptr, &control, sizeof(control));
                v4l2element->controls = g_list_append(v4l2element->controls, ctrlptr);
@@ -216,11 +205,6 @@ gst_v4l2_empty_lists (GstV4l2Element *v4l2element)
                v4l2element->norms = g_list_remove(v4l2element->norms, data);
                g_free(data);
        }
-       while (g_list_length(v4l2element->formats) > 0) {
-               gpointer data = g_list_nth_data(v4l2element->formats, 0);
-               v4l2element->formats = g_list_remove(v4l2element->formats, data);
-               g_free(data);
-       }
        while (g_list_length(v4l2element->controls) > 0) {
                gpointer data = g_list_nth_data(v4l2element->controls, 0);
                v4l2element->controls = g_list_remove(v4l2element->controls, data);
@@ -275,7 +259,7 @@ gst_v4l2_open (GstV4l2Element *v4l2element)
                goto error;
 
        gst_info("Opened device '%s' (%s) successfully\n",
-               v4l2element->vcap.name, v4l2element->device);
+               v4l2element->vcap.card, v4l2element->device);
 
        return TRUE;
 
@@ -326,13 +310,13 @@ gboolean
 gst_v4l2_get_norm (GstV4l2Element *v4l2element,
                    gint           *norm)
 {
-       struct v4l2_standard standard;
+       v4l2_std_id std_id;
        gint n;
 
        DEBUG("getting norm");
        GST_V4L2_CHECK_OPEN(v4l2element);
 
-       if (ioctl(v4l2element->video_fd, VIDIOC_G_STD, &standard) < 0) {
+       if (ioctl(v4l2element->video_fd, VIDIOC_G_STD, &std_id) < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
                        "Failed to get the current norm for device %s: %s",
                        v4l2element->device, g_strerror(errno));
@@ -341,16 +325,16 @@ gst_v4l2_get_norm (GstV4l2Element *v4l2element,
 
        /* try to find out what norm number this actually is */
        for (n=0;n<g_list_length(v4l2element->norms);n++) {
-               struct v4l2_enumstd *stdptr = (struct v4l2_enumstd *) g_list_nth_data(v4l2element->norms, n);
-               if (!strcmp(stdptr->std.name, standard.name)) {
+               struct v4l2_standard *stdptr = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, n);
+               if (stdptr->id == std_id) {
                        *norm = n;
                        return TRUE;
                }
        }
 
        gst_element_error(GST_ELEMENT(v4l2element),
-               "Failed to find norm '%s' in our list of available norms for device %s",
-               standard.name, v4l2element->device);
+               "Failed to find norm '%llu' in our list of available norms for device %s",
+               std_id, v4l2element->device);
        return FALSE;
 }
 
@@ -365,7 +349,7 @@ gboolean
 gst_v4l2_set_norm (GstV4l2Element *v4l2element,
                    gint            norm)
 {
-       struct v4l2_enumstd *standard;
+       struct v4l2_standard *standard;
 
        DEBUG("trying to set norm to %d", norm);
        GST_V4L2_CHECK_OPEN(v4l2element);
@@ -378,12 +362,12 @@ gst_v4l2_set_norm (GstV4l2Element *v4l2element,
                return FALSE;
        }
 
-       standard = (struct v4l2_enumstd *) g_list_nth_data(v4l2element->norms, norm);
+       standard = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, norm);
 
-       if (ioctl(v4l2element->video_fd, VIDIOC_S_STD, &standard->std) < 0) {
+       if (ioctl(v4l2element->video_fd, VIDIOC_S_STD, &standard->id) < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
-                       "Failed to set norm '%s' (%d) for device %s: %s",
-                       standard->std.name, norm, v4l2element->device, g_strerror(errno));
+                       "Failed to set norm '%s' (%llu) for device %s: %s",
+                       standard->name, standard->id, v4l2element->device, g_strerror(errno));
                return FALSE;
        }
 
@@ -406,8 +390,8 @@ gst_v4l2_get_norm_names (GstV4l2Element *v4l2element)
        DEBUG("getting a list of norm names");
 
        for (n=0;n<g_list_length(v4l2element->norms);n++) {
-               struct v4l2_enumstd *standard = (struct v4l2_enumstd *) g_list_nth_data(v4l2element->norms, n);
-               names = g_list_append(names, g_strdup(standard->std.name));
+               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;
@@ -586,8 +570,9 @@ gst_v4l2_get_output_names (GstV4l2Element *v4l2element)
  * return value: TRUE if it has a tuner, else FALSE
  ******************************************************/
 
-gboolean
-gst_v4l2_has_tuner (GstV4l2Element *v4l2element)
+gint
+gst_v4l2_has_tuner (GstV4l2Element *v4l2element,
+                    gint           *tuner_num)
 {
        gint input_num;
        struct v4l2_input *input;
@@ -600,8 +585,12 @@ gst_v4l2_has_tuner (GstV4l2Element *v4l2element)
 
        input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num);
 
-       return (input->type == V4L2_INPUT_TYPE_TUNER &&
-               v4l2element->vcap.flags & V4L2_FLAG_TUNER);
+       if (input->type == V4L2_INPUT_TYPE_TUNER &&
+           v4l2element->vcap.capabilities & V4L2_CAP_TUNER) {
+               *tuner_num = input->tuner;
+               return TRUE;
+       }
+       return FALSE;
 }
 
 
@@ -615,22 +604,24 @@ gboolean
 gst_v4l2_get_frequency (GstV4l2Element *v4l2element,
                         gulong         *frequency)
 {
-       gint n;
+       struct v4l2_frequency freq;
 
        DEBUG("getting current tuner frequency");
        GST_V4L2_CHECK_OPEN(v4l2element);
 
-       if (!gst_v4l2_has_tuner(v4l2element))
+       if (!gst_v4l2_has_tuner(v4l2element, &freq.tuner))
                return FALSE;
 
-       if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQ, &n) < 0) {
+       freq.type = 0;
+
+       if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
                        "Failed to get current tuner frequency for device %s: %s",
                        v4l2element->device, g_strerror(errno));
                return FALSE;
        }
 
-       *frequency = n;
+       *frequency = freq.frequency;
 
        return TRUE;
 }
@@ -646,16 +637,19 @@ gboolean
 gst_v4l2_set_frequency (GstV4l2Element *v4l2element,
                         gulong          frequency)
 {
-       gint n = frequency;
+       struct v4l2_frequency freq;
 
        DEBUG("setting current tuner frequency to %lu", frequency);
        GST_V4L2_CHECK_OPEN(v4l2element);
        GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
 
-       if (!gst_v4l2_has_tuner(v4l2element))
+       if (!gst_v4l2_has_tuner(v4l2element, &freq.tuner))
                return FALSE;
 
-       if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQ, &n) < 0) {
+       freq.frequency = frequency;
+       freq.type = 0;
+
+       if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
                        "Failed to set tuner frequency to %lu for device %s: %s",
                        frequency, v4l2element->device, g_strerror(errno));
@@ -683,7 +677,7 @@ gst_v4l2_signal_strength (GstV4l2Element *v4l2element,
 
        if (ioctl(v4l2element->video_fd, VIDIOC_G_TUNER, &tuner) < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
-                       "Failed to set signal strength for device %s: %s",
+                       "Failed to get signal strength for device %s: %s",
                        v4l2element->device, g_strerror(errno));
                return FALSE;
        }
@@ -714,7 +708,7 @@ gst_v4l2_has_audio (GstV4l2Element *v4l2element)
 
        input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num);
 
-       return (input->capability & V4L2_INPUT_CAP_AUDIO);
+       return (input->audioset != 0);
 }
 
 
@@ -738,36 +732,47 @@ gst_v4l2_get_attributes   (GstV4l2Element *v4l2element)
                attribute->name = g_strdup(control->name);
                attribute->index = i;
                attribute->list_items = NULL;
-               switch (control->type) {
-                       case V4L2_CTRL_TYPE_INTEGER:
-                               attribute->val_type = GST_V4L2_ATTRIBUTE_VALUE_TYPE_INT;
-                               break;
-                       case V4L2_CTRL_TYPE_BOOLEAN:
-                               attribute->val_type = GST_V4L2_ATTRIBUTE_VALUE_TYPE_BOOLEAN;
-                               break;
-                       case 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));
-                               }
-                               attribute->val_type = GST_V4L2_ATTRIBUTE_VALUE_TYPE_LIST;
-                               break; }
-                       case V4L2_CTRL_TYPE_BUTTON:
-                               attribute->val_type = GST_V4L2_ATTRIBUTE_VALUE_TYPE_BUTTON;
-                               break;
+               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->category) {
-                       case V4L2_CTRL_CAT_VIDEO:
+               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_CTRL_CAT_AUDIO:
+                       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;
-                       case V4L2_CTRL_CAT_EFFECT:
-                               attribute->type = GST_V4L2_ATTRIBUTE_TYPE_EFFECT;
+                       default:
+                               attribute->type = GST_V4L2_ATTRIBUTE_TYPE_OTHER;
                                break;
                }
                gst_v4l2_get_attribute(v4l2element, i, &attribute->value);
index de0bbc9..db9adc0 100644 (file)
   (v4l2element->buffer != NULL)
 
 #define GST_V4L2_IS_OVERLAY(v4l2element) \
-  (v4l2element->vcap.flags & V4L2_FLAG_PREVIEW)
+  (v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
 
 /* checks whether the current v4lelement has already been open()'ed or not */
 #define GST_V4L2_CHECK_OPEN(v4l2element) \
-  if (v4l2element->video_fd <= 0)               \
+  if (!GST_V4L2_IS_OPEN(v4l2element))           \
   {                                             \
     gst_element_error(GST_ELEMENT(v4l2element), \
       "Device is not open");                    \
@@ -45,7 +45,7 @@
 
 /* checks whether the current v4lelement is close()'ed or whether it is still open */
 #define GST_V4L2_CHECK_NOT_OPEN(v4l2element) \
-  if (v4l2element->video_fd != -1)              \
+  if (GST_V4L2_IS_OPEN(v4l2element))            \
   {                                             \
     gst_element_error(GST_ELEMENT(v4l2element), \
       "Device is open");                        \
 
 /* checks whether the current v4lelement does video overlay */
 #define GST_V4L2_CHECK_OVERLAY(v4l2element) \
-  if (!(v4l2element->vcap.flags & V4L2_FLAG_PREVIEW)) \
-  {                                                   \
-    gst_element_error(GST_ELEMENT(v4l2element),       \
-      "Device doesn't do overlay");                   \
-    return FALSE;                                     \
+  if (!GST_V4L2_IS_OVERLAY(v4l2element))        \
+  {                                             \
+    gst_element_error(GST_ELEMENT(v4l2element), \
+      "Device doesn't do overlay");             \
+    return FALSE;                               \
   }
 
 /* checks whether we're in capture mode or not */
 #define GST_V4L2_CHECK_ACTIVE(v4l2element) \
-  if (v4l2element->buffer == NULL)              \
+  if (!GST_V4L2_IS_ACTIVE(v4l2element))         \
   {                                             \
     gst_element_error(GST_ELEMENT(v4l2element), \
       "Device is not in streaming mode");       \
@@ -72,7 +72,7 @@
 
 /* checks whether we're out of capture mode or not */
 #define GST_V4L2_CHECK_NOT_ACTIVE(v4l2element) \
-  if (v4l2element->buffer != NULL)              \
+  if (GST_V4L2_IS_ACTIVE(v4l2element))          \
   {                                             \
     gst_element_error(GST_ELEMENT(v4l2element), \
       "Device is in streaming mode");           \
@@ -102,7 +102,8 @@ gboolean    gst_v4l2_set_output             (GstV4l2Element *v4l2element,
 GList *                gst_v4l2_get_output_names       (GstV4l2Element *v4l2element);
 
 /* frequency control */
-gboolean       gst_v4l2_has_tuner              (GstV4l2Element *v4l2element);
+gboolean       gst_v4l2_has_tuner              (GstV4l2Element *v4l2element,
+                                                gint           *tuner_num);
 gboolean       gst_v4l2_get_frequency          (GstV4l2Element *v4l2element,
                                                 gulong         *frequency);
 gboolean       gst_v4l2_set_frequency          (GstV4l2Element *v4l2element,
index 9215de1..a6f244f 100644 (file)
 
 
 /******************************************************
+ * gst_v4l2src_fill_format_list():
+ *   create list of supported capture formats
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+
+gboolean
+gst_v4l2src_fill_format_list (GstV4l2Src *v4l2src)
+{
+       gint n;
+
+       DEBUG("getting src format enumerations");
+
+       /* format enumeration */
+       for (n=0;;n++) {
+               struct v4l2_fmtdesc format, *fmtptr;
+               format.index = n;
+               format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               if (ioctl(GST_V4L2ELEMENT(v4l2src)->video_fd, VIDIOC_ENUM_FMT, &format) < 0) {
+                       if (errno == EINVAL)
+                               break; /* end of enumeration */
+                       else {
+                               gst_element_error(GST_ELEMENT(v4l2src),
+                                       "Failed to get no. %d in pixelformat enumeration for %s: %s",
+                                       n, GST_V4L2ELEMENT(v4l2src)->device, g_strerror(errno));
+                               return FALSE;
+                       }
+               }
+               fmtptr = g_malloc(sizeof(format));
+               memcpy(fmtptr, &format, sizeof(format));
+               v4l2src->formats = g_list_append(v4l2src->formats, fmtptr);
+       }
+
+       return TRUE;
+}
+
+
+/******************************************************
+ * gst_v4l2src_empty_format_list():
+ *   free list of supported capture formats
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+
+gboolean
+gst_v4l2src_empty_format_list (GstV4l2Src *v4l2src)
+{
+       while (g_list_length(v4l2src->formats) > 0) {
+               gpointer data = g_list_nth_data(v4l2src->formats, 0);
+               v4l2src->formats = g_list_remove(v4l2src->formats, data);
+               g_free(data);
+       }
+
+       return TRUE;
+}
+
+
+/******************************************************
  * gst_v4l2src_queue_frame():
  *   queue a frame for capturing
  * return value: TRUE on success, FALSE on error
@@ -101,6 +157,7 @@ gst_v4l2src_get_capture (GstV4l2Src *v4l2src)
 
        GST_V4L2_CHECK_OPEN(GST_V4L2ELEMENT(v4l2src));
 
+       v4l2src->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (ioctl(GST_V4L2ELEMENT(v4l2src)->video_fd, VIDIOC_G_FMT, &v4l2src->format) < 0) {
                gst_element_error(GST_ELEMENT(v4l2src),
                        "Failed to get pixel format for device %s: %s",
@@ -134,12 +191,7 @@ gst_v4l2src_set_capture (GstV4l2Src          *v4l2src,
        v4l2src->format.fmt.pix.width = width;
        v4l2src->format.fmt.pix.height = height;
        v4l2src->format.fmt.pix.pixelformat = fmt->pixelformat;
-       if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
-               v4l2src->format.fmt.pix.flags = V4L2_FMT_FLAG_COMPRESSED;
-               v4l2src->format.type = V4L2_BUF_TYPE_CODECIN;
-       } else {
-               v4l2src->format.type = V4L2_BUF_TYPE_CAPTURE;
-       }
+       v4l2src->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
        if (ioctl(GST_V4L2ELEMENT(v4l2src)->video_fd, VIDIOC_S_FMT, &v4l2src->format) < 0) {
                gst_element_error(GST_ELEMENT(v4l2src),
@@ -189,8 +241,8 @@ gst_v4l2src_capture_init (GstV4l2Src *v4l2src)
        }
        v4l2src->bufsettings.type = v4l2src->format.type;
 
-       for (n=0;n<g_list_length(GST_V4L2ELEMENT(v4l2src)->formats);n++) {
-               struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->formats, 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);
                if (v4l2src->format.fmt.pix.pixelformat == fmt->pixelformat) {
                        desc = fmt->description;
                        break;
@@ -359,11 +411,10 @@ GList *
 gst_v4l2src_get_fourcc_list (GstV4l2Src *v4l2src)
 {
        GList *list = NULL;
-       GstV4l2Element *v4l2element = GST_V4L2ELEMENT(v4l2src);
        gint n;
 
-       for (n=0;n<g_list_length(v4l2element->formats);n++) {
-               struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2element->formats, 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;
 
@@ -384,11 +435,10 @@ GList *
 gst_v4l2src_get_format_list (GstV4l2Src *v4l2src)
 {
        GList *list = NULL;
-       GstV4l2Element *v4l2element = GST_V4L2ELEMENT(v4l2src);
        gint n;
 
-       for (n=0;n<g_list_length(v4l2element->formats);n++) {
-               struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2element->formats, 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));
        }
index c9a108a..436f65d 100644 (file)
@@ -38,6 +38,8 @@ gboolean      gst_v4l2src_requeue_frame       (GstV4l2Src *v4l2src,
 gboolean       gst_v4l2src_capture_stop        (GstV4l2Src *v4l2src);
 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);