gst_plugins_base/sys/v4l/gstv4lelement.c
branchRCL_3
changeset 30 7e817e7e631c
parent 0 0e761a78d257
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
       
     1 /* GStreamer
       
     2  *
       
     3  * gstv4lelement.c: base class for V4L elements
       
     4  *
       
     5  * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Library General Public
       
     9  * License as published by the Free Software Foundation; either
       
    10  * version 2 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Library General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Library General Public
       
    18  * License along with this library; if not, write to the
       
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    20  * Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 #ifdef HAVE_CONFIG_H
       
    24 #include <config.h>
       
    25 #endif
       
    26 
       
    27 #include <sys/stat.h>
       
    28 #include <fcntl.h>
       
    29 #include <errno.h>
       
    30 #include <unistd.h>
       
    31 #include <string.h>
       
    32 
       
    33 #include <gst/interfaces/propertyprobe.h>
       
    34 
       
    35 #include "v4l_calls.h"
       
    36 #include "gstv4ltuner.h"
       
    37 #ifdef HAVE_XVIDEO
       
    38 #include "gstv4lxoverlay.h"
       
    39 #endif
       
    40 #include "gstv4lcolorbalance.h"
       
    41 
       
    42 
       
    43 enum
       
    44 {
       
    45   PROP_0,
       
    46   PROP_DEVICE,
       
    47   PROP_DEVICE_NAME,
       
    48   PROP_FLAGS
       
    49 };
       
    50 
       
    51 
       
    52 static void gst_v4lelement_init_interfaces (GType type);
       
    53 
       
    54 GST_BOILERPLATE_FULL (GstV4lElement, gst_v4lelement, GstPushSrc,
       
    55     GST_TYPE_PUSH_SRC, gst_v4lelement_init_interfaces);
       
    56 
       
    57 
       
    58 static void gst_v4lelement_dispose (GObject * object);
       
    59 static void gst_v4lelement_set_property (GObject * object,
       
    60     guint prop_id, const GValue * value, GParamSpec * pspec);
       
    61 static void gst_v4lelement_get_property (GObject * object,
       
    62     guint prop_id, GValue * value, GParamSpec * pspec);
       
    63 static gboolean gst_v4lelement_start (GstBaseSrc * src);
       
    64 static gboolean gst_v4lelement_stop (GstBaseSrc * src);
       
    65 
       
    66 
       
    67 static gboolean
       
    68 gst_v4l_iface_supported (GstImplementsInterface * iface, GType iface_type)
       
    69 {
       
    70   GstV4lElement *v4lelement = GST_V4LELEMENT (iface);
       
    71 
       
    72 #ifdef HAVE_XVIDEO
       
    73   g_assert (iface_type == GST_TYPE_TUNER ||
       
    74       iface_type == GST_TYPE_X_OVERLAY || iface_type == GST_TYPE_COLOR_BALANCE);
       
    75 #else
       
    76   g_assert (iface_type == GST_TYPE_TUNER ||
       
    77       iface_type == GST_TYPE_COLOR_BALANCE);
       
    78 #endif
       
    79 
       
    80   if (v4lelement->video_fd == -1)
       
    81     return FALSE;
       
    82 
       
    83 #ifdef HAVE_XVIDEO
       
    84   if (iface_type == GST_TYPE_X_OVERLAY && !GST_V4L_IS_OVERLAY (v4lelement))
       
    85     return FALSE;
       
    86 #endif
       
    87 
       
    88   return TRUE;
       
    89 }
       
    90 
       
    91 static void
       
    92 gst_v4l_interface_init (GstImplementsInterfaceClass * klass)
       
    93 {
       
    94   /* default virtual functions */
       
    95   klass->supported = gst_v4l_iface_supported;
       
    96 }
       
    97 
       
    98 static const GList *
       
    99 gst_v4l_probe_get_properties (GstPropertyProbe * probe)
       
   100 {
       
   101   GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
       
   102   static GList *list = NULL;
       
   103 
       
   104   if (!list) {
       
   105     list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
       
   106   }
       
   107 
       
   108   return list;
       
   109 }
       
   110 
       
   111 static gboolean
       
   112 gst_v4l_class_probe_devices (GstV4lElementClass * klass, gboolean check)
       
   113 {
       
   114   static gboolean init = FALSE;
       
   115   static GList *devices = NULL;
       
   116 
       
   117   if (!init && !check) {
       
   118     gchar *dev_base[] = { "/dev/video", "/dev/v4l/video", NULL };
       
   119     gint base, n, fd;
       
   120 
       
   121     while (devices) {
       
   122       GList *item = devices;
       
   123       gchar *device = item->data;
       
   124 
       
   125       devices = g_list_remove (devices, item);
       
   126       g_free (device);
       
   127     }
       
   128 
       
   129     /* detect /dev entries */
       
   130     for (n = 0; n < 64; n++) {
       
   131       for (base = 0; dev_base[base] != NULL; base++) {
       
   132         struct stat s;
       
   133         gchar *device = g_strdup_printf ("%s%d", dev_base[base], n);
       
   134 
       
   135         /* does the /dev/ entry exist at all? */
       
   136         if (stat (device, &s) == 0) {
       
   137           /* yes: is a device attached? */
       
   138           if ((fd = open (device, O_RDONLY)) > 0 || errno == EBUSY) {
       
   139             if (fd > 0)
       
   140               close (fd);
       
   141 
       
   142             devices = g_list_append (devices, device);
       
   143             break;
       
   144           }
       
   145         }
       
   146         g_free (device);
       
   147       }
       
   148     }
       
   149 
       
   150     init = TRUE;
       
   151   }
       
   152 
       
   153   klass->devices = devices;
       
   154 
       
   155   return init;
       
   156 }
       
   157 
       
   158 static void
       
   159 gst_v4l_probe_probe_property (GstPropertyProbe * probe,
       
   160     guint prop_id, const GParamSpec * pspec)
       
   161 {
       
   162   GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe);
       
   163 
       
   164   switch (prop_id) {
       
   165     case PROP_DEVICE:
       
   166       gst_v4l_class_probe_devices (klass, FALSE);
       
   167       break;
       
   168     default:
       
   169       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
       
   170       break;
       
   171   }
       
   172 }
       
   173 
       
   174 static gboolean
       
   175 gst_v4l_probe_needs_probe (GstPropertyProbe * probe,
       
   176     guint prop_id, const GParamSpec * pspec)
       
   177 {
       
   178   GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe);
       
   179   gboolean ret = FALSE;
       
   180 
       
   181   switch (prop_id) {
       
   182     case PROP_DEVICE:
       
   183       ret = !gst_v4l_class_probe_devices (klass, TRUE);
       
   184       break;
       
   185     default:
       
   186       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
       
   187       break;
       
   188   }
       
   189 
       
   190   return ret;
       
   191 }
       
   192 
       
   193 static GValueArray *
       
   194 gst_v4l_class_list_devices (GstV4lElementClass * klass)
       
   195 {
       
   196   GValueArray *array;
       
   197   GValue value = { 0 };
       
   198   GList *item;
       
   199 
       
   200   if (!klass->devices)
       
   201     return NULL;
       
   202 
       
   203   array = g_value_array_new (g_list_length (klass->devices));
       
   204   item = klass->devices;
       
   205   g_value_init (&value, G_TYPE_STRING);
       
   206   while (item) {
       
   207     gchar *device = item->data;
       
   208 
       
   209     g_value_set_string (&value, device);
       
   210     g_value_array_append (array, &value);
       
   211 
       
   212     item = item->next;
       
   213   }
       
   214   g_value_unset (&value);
       
   215 
       
   216   return array;
       
   217 }
       
   218 
       
   219 static GValueArray *
       
   220 gst_v4l_probe_get_values (GstPropertyProbe * probe,
       
   221     guint prop_id, const GParamSpec * pspec)
       
   222 {
       
   223   GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe);
       
   224   GValueArray *array = NULL;
       
   225 
       
   226   switch (prop_id) {
       
   227     case PROP_DEVICE:
       
   228       array = gst_v4l_class_list_devices (klass);
       
   229       break;
       
   230     default:
       
   231       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
       
   232       break;
       
   233   }
       
   234 
       
   235   return array;
       
   236 }
       
   237 
       
   238 static void
       
   239 gst_v4l_property_probe_interface_init (GstPropertyProbeInterface * iface)
       
   240 {
       
   241   iface->get_properties = gst_v4l_probe_get_properties;
       
   242   iface->probe_property = gst_v4l_probe_probe_property;
       
   243   iface->needs_probe = gst_v4l_probe_needs_probe;
       
   244   iface->get_values = gst_v4l_probe_get_values;
       
   245 }
       
   246 
       
   247 #define GST_TYPE_V4L_DEVICE_FLAGS (gst_v4l_device_get_type ())
       
   248 static GType
       
   249 gst_v4l_device_get_type (void)
       
   250 {
       
   251   static GType v4l_device_type = 0;
       
   252 
       
   253   if (v4l_device_type == 0) {
       
   254     static const GFlagsValue values[] = {
       
   255       {VID_TYPE_CAPTURE, "CAPTURE", "Device can capture"},
       
   256       {VID_TYPE_TUNER, "TUNER", "Device has a tuner"},
       
   257       {VID_TYPE_OVERLAY, "OVERLAY", "Device can do overlay"},
       
   258       {VID_TYPE_MPEG_DECODER, "MPEG_DECODER", "Device can decode MPEG"},
       
   259       {VID_TYPE_MPEG_ENCODER, "MPEG_ENCODER", "Device can encode MPEG"},
       
   260       {VID_TYPE_MJPEG_DECODER, "MJPEG_DECODER", "Device can decode MJPEG"},
       
   261       {VID_TYPE_MJPEG_ENCODER, "MJPEG_ENCODER", "Device can encode MJPEG"},
       
   262       {0x10000, "AUDIO", "Device handles audio"},
       
   263       {0, NULL, NULL}
       
   264     };
       
   265 
       
   266     v4l_device_type = g_flags_register_static ("GstV4lDeviceTypeFlags", values);
       
   267   }
       
   268 
       
   269   return v4l_device_type;
       
   270 }
       
   271 
       
   272 static void
       
   273 gst_v4lelement_init_interfaces (GType type)
       
   274 {
       
   275   static const GInterfaceInfo v4liface_info = {
       
   276     (GInterfaceInitFunc) gst_v4l_interface_init,
       
   277     NULL,
       
   278     NULL,
       
   279   };
       
   280   static const GInterfaceInfo v4l_tuner_info = {
       
   281     (GInterfaceInitFunc) gst_v4l_tuner_interface_init,
       
   282     NULL,
       
   283     NULL,
       
   284   };
       
   285 #ifdef HAVE_XVIDEO
       
   286   static const GInterfaceInfo v4l_xoverlay_info = {
       
   287     (GInterfaceInitFunc) gst_v4l_xoverlay_interface_init,
       
   288     NULL,
       
   289     NULL,
       
   290   };
       
   291 #endif
       
   292   static const GInterfaceInfo v4l_colorbalance_info = {
       
   293     (GInterfaceInitFunc) gst_v4l_color_balance_interface_init,
       
   294     NULL,
       
   295     NULL,
       
   296   };
       
   297   static const GInterfaceInfo v4l_propertyprobe_info = {
       
   298     (GInterfaceInitFunc) gst_v4l_property_probe_interface_init,
       
   299     NULL,
       
   300     NULL,
       
   301   };
       
   302 
       
   303   g_type_add_interface_static (type,
       
   304       GST_TYPE_IMPLEMENTS_INTERFACE, &v4liface_info);
       
   305   g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l_tuner_info);
       
   306 #ifdef HAVE_XVIDEO
       
   307   g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l_xoverlay_info);
       
   308 #endif
       
   309   g_type_add_interface_static (type,
       
   310       GST_TYPE_COLOR_BALANCE, &v4l_colorbalance_info);
       
   311   g_type_add_interface_static (type,
       
   312       GST_TYPE_PROPERTY_PROBE, &v4l_propertyprobe_info);
       
   313 }
       
   314 
       
   315 
       
   316 static void
       
   317 gst_v4lelement_base_init (gpointer g_class)
       
   318 {
       
   319   GstV4lElementClass *klass = GST_V4LELEMENT_CLASS (g_class);
       
   320 
       
   321   klass->devices = NULL;
       
   322 }
       
   323 
       
   324 static void
       
   325 gst_v4lelement_class_init (GstV4lElementClass * klass)
       
   326 {
       
   327   GObjectClass *gobject_class;
       
   328   GstBaseSrcClass *basesrc_class;
       
   329 
       
   330   gobject_class = (GObjectClass *) klass;
       
   331   basesrc_class = (GstBaseSrcClass *) klass;
       
   332 
       
   333   gobject_class->set_property = gst_v4lelement_set_property;
       
   334   gobject_class->get_property = gst_v4lelement_get_property;
       
   335 
       
   336   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE,
       
   337       g_param_spec_string ("device", "Device", "Device location",
       
   338           NULL, G_PARAM_READWRITE));
       
   339   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE_NAME,
       
   340       g_param_spec_string ("device_name", "Device name", "Name of the device",
       
   341           NULL, G_PARAM_READABLE));
       
   342   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FLAGS,
       
   343       g_param_spec_flags ("flags", "Flags", "Device type flags",
       
   344           GST_TYPE_V4L_DEVICE_FLAGS, 0, G_PARAM_READABLE));
       
   345 
       
   346   basesrc_class->start = gst_v4lelement_start;
       
   347   basesrc_class->stop = gst_v4lelement_stop;
       
   348 
       
   349   gobject_class->dispose = gst_v4lelement_dispose;
       
   350 }
       
   351 
       
   352 
       
   353 static void
       
   354 gst_v4lelement_init (GstV4lElement * v4lelement, GstV4lElementClass * klass)
       
   355 {
       
   356   /* some default values */
       
   357   v4lelement->video_fd = -1;
       
   358   v4lelement->buffer = NULL;
       
   359   v4lelement->videodev = g_strdup ("/dev/video0");
       
   360 
       
   361   v4lelement->norms = NULL;
       
   362   v4lelement->channels = NULL;
       
   363   v4lelement->colors = NULL;
       
   364 
       
   365   v4lelement->xwindow_id = 0;
       
   366 }
       
   367 
       
   368 
       
   369 static void
       
   370 gst_v4lelement_dispose (GObject * object)
       
   371 {
       
   372   GstV4lElement *v4lelement = GST_V4LELEMENT (object);
       
   373 
       
   374   if (v4lelement->videodev) {
       
   375     g_free (v4lelement->videodev);
       
   376     v4lelement->videodev = NULL;
       
   377   }
       
   378 
       
   379   if (((GObjectClass *) parent_class)->dispose)
       
   380     ((GObjectClass *) parent_class)->dispose (object);
       
   381 }
       
   382 
       
   383 
       
   384 static void
       
   385 gst_v4lelement_set_property (GObject * object,
       
   386     guint prop_id, const GValue * value, GParamSpec * pspec)
       
   387 {
       
   388   GstV4lElement *v4lelement = GST_V4LELEMENT (object);
       
   389 
       
   390   switch (prop_id) {
       
   391     case PROP_DEVICE:
       
   392       if (v4lelement->videodev)
       
   393         g_free (v4lelement->videodev);
       
   394       v4lelement->videodev = g_strdup (g_value_get_string (value));
       
   395       break;
       
   396     default:
       
   397       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   398       break;
       
   399   }
       
   400 }
       
   401 
       
   402 
       
   403 static void
       
   404 gst_v4lelement_get_property (GObject * object,
       
   405     guint prop_id, GValue * value, GParamSpec * pspec)
       
   406 {
       
   407   GstV4lElement *v4lelement = GST_V4LELEMENT (object);
       
   408 
       
   409   switch (prop_id) {
       
   410     case PROP_DEVICE:
       
   411       g_value_set_string (value, v4lelement->videodev);
       
   412       break;
       
   413     case PROP_DEVICE_NAME:{
       
   414       gchar *new = NULL;
       
   415 
       
   416       if (GST_V4L_IS_OPEN (v4lelement)) {
       
   417         new = v4lelement->vcap.name;
       
   418       } else if (gst_v4l_open (v4lelement)) {
       
   419         new = v4lelement->vcap.name;
       
   420         gst_v4l_close (v4lelement);
       
   421       }
       
   422       g_value_set_string (value, new);
       
   423       break;
       
   424     }
       
   425     case PROP_FLAGS:{
       
   426       guint flags = 0;
       
   427 
       
   428       if (GST_V4L_IS_OPEN (v4lelement)) {
       
   429         flags |= v4lelement->vcap.type & 0x3C0B;
       
   430         if (v4lelement->vcap.audios)
       
   431           flags |= 0x10000;
       
   432       }
       
   433       g_value_set_flags (value, flags);
       
   434       break;
       
   435     }
       
   436     default:
       
   437       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   438       break;
       
   439   }
       
   440 }
       
   441 
       
   442 static gboolean
       
   443 gst_v4lelement_start (GstBaseSrc * src)
       
   444 {
       
   445   GstV4lElement *v4lelement = GST_V4LELEMENT (src);
       
   446 
       
   447   if (!gst_v4l_open (v4lelement))
       
   448     return FALSE;
       
   449 
       
   450 #ifdef HAVE_XVIDEO
       
   451   gst_v4l_xoverlay_start (v4lelement);
       
   452 #endif
       
   453 
       
   454   return TRUE;
       
   455 }
       
   456 
       
   457 static gboolean
       
   458 gst_v4lelement_stop (GstBaseSrc * src)
       
   459 {
       
   460   GstV4lElement *v4lelement = GST_V4LELEMENT (src);
       
   461 
       
   462 #ifdef HAVE_XVIDEO
       
   463   gst_v4l_xoverlay_stop (v4lelement);
       
   464 #endif
       
   465 
       
   466   if (!gst_v4l_close (v4lelement))
       
   467     return FALSE;
       
   468 
       
   469   return TRUE;
       
   470 }