source: trunk/third/gst-plugins/sys/qcam/gstqcamsrc.c @ 21011

Revision 21011, 12.9 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21010, which included commits to RCS files with non-trunk default branches.
Line 
1/* GStreamer
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <sys/ioctl.h>
27#include <sys/mman.h>
28#include <string.h>
29
30/*#define DEBUG_ENABLED */
31#include <gstqcamsrc.h>
32#include <gst/video/video.h>
33
34#include "qcamip.h"
35
36/* elementfactory information */
37static GstElementDetails gst_qcamsrc_details =
38GST_ELEMENT_DETAILS ("QCam Source",
39    "Source/Video",
40    "Read from a QuickCam device",
41    "Wim Taymans <wim.taymans@chello.be>");
42
43#define AE_NONE                 3
44
45#define DEF_WIDTH               320
46#define DEF_HEIGHT              224
47#define DEF_BRIGHTNESS          226
48#define DEF_WHITEBAL            128
49#define DEF_CONTRAST            72
50#define DEF_TOP                 1
51#define DEF_LEFT                14
52#define DEF_TRANSFER_SCALE      2
53#define DEF_DEPTH               6
54#define DEF_PORT                0x378
55#define DEF_AUTOEXP             AE_NONE
56
57static GstStaticPadTemplate gst_qcamsrc_src_factory =
58GST_STATIC_PAD_TEMPLATE ("src",
59    GST_PAD_SRC,
60    GST_PAD_ALWAYS,
61    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
62    );
63
64#define GST_TYPE_AUTOEXP_MODE (gst_autoexp_mode_get_type())
65static GType
66gst_autoexp_mode_get_type (void)
67{
68  static GType autoexp_mode_type = 0;
69  static GEnumValue autoexp_modes[] = {
70    {AE_ALL_AVG, "0", "Average Picture"},
71    {AE_CTR_AVG, "1", "Average Center"},
72    {AE_STD_AVG, "2", "Standard Deviation"},
73    {AE_NONE, "3", "None"},
74    {0, NULL, NULL},
75  };
76
77  if (!autoexp_mode_type) {
78    autoexp_mode_type =
79        g_enum_register_static ("GstAutoExposureMode", autoexp_modes);
80  }
81  return autoexp_mode_type;
82}
83
84/* QCamSrc signals and args */
85enum
86{
87  /* FILL ME */
88  LAST_SIGNAL
89};
90
91enum
92{
93  ARG_0,
94  ARG_WIDTH,
95  ARG_HEIGHT,
96  ARG_BRIGHTNESS,
97  ARG_WHITEBAL,
98  ARG_CONTRAST,
99  ARG_TOP,
100  ARG_LEFT,
101  ARG_TRANSFER_SCALE,
102  ARG_DEPTH,
103  ARG_PORT,
104  ARG_AUTOEXP
105};
106
107static void gst_qcamsrc_base_init (gpointer g_class);
108static void gst_qcamsrc_class_init (GstQCamSrcClass * klass);
109static void gst_qcamsrc_init (GstQCamSrc * qcamsrc);
110
111static void gst_qcamsrc_set_property (GObject * object, guint prop_id,
112    const GValue * value, GParamSpec * pspec);
113static void gst_qcamsrc_get_property (GObject * object, guint prop_id,
114    GValue * value, GParamSpec * pspec);
115
116static GstElementStateReturn gst_qcamsrc_change_state (GstElement * element);
117static void gst_qcamsrc_close (GstQCamSrc * src);
118static gboolean gst_qcamsrc_open (GstQCamSrc * src);
119
120static GstData *gst_qcamsrc_get (GstPad * pad);
121
122static GstElementClass *parent_class = NULL;
123
124/*//static guint gst_qcamsrc_signals[LAST_SIGNAL] = { 0 }; */
125
126GType
127gst_qcamsrc_get_type (void)
128{
129  static GType qcamsrc_type = 0;
130
131  if (!qcamsrc_type) {
132    static const GTypeInfo qcamsrc_info = {
133      sizeof (GstQCamSrcClass),
134      gst_qcamsrc_base_init,
135      NULL,
136      (GClassInitFunc) gst_qcamsrc_class_init,
137      NULL,
138      NULL,
139      sizeof (GstQCamSrc),
140      0,
141      (GInstanceInitFunc) gst_qcamsrc_init,
142      NULL
143    };
144
145    qcamsrc_type =
146        g_type_register_static (GST_TYPE_ELEMENT, "GstQCamSrc", &qcamsrc_info,
147        0);
148  }
149  return qcamsrc_type;
150}
151static void
152gst_qcamsrc_base_init (gpointer g_class)
153{
154  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
155
156  gst_element_class_add_pad_template (element_class,
157      gst_static_pad_template_get (&gst_qcamsrc_src_factory));
158  gst_element_class_set_details (element_class, &gst_qcamsrc_details);
159}
160static void
161gst_qcamsrc_class_init (GstQCamSrcClass * klass)
162{
163  GObjectClass *gobject_class;
164  GstElementClass *gstelement_class;
165
166  gobject_class = (GObjectClass *) klass;
167  gstelement_class = (GstElementClass *) klass;
168
169  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
170
171  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_WIDTH,
172      g_param_spec_int ("width", "width", "width",
173          0, 320, DEF_WIDTH, G_PARAM_READWRITE));
174  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HEIGHT,
175      g_param_spec_int ("height", "height", "height",
176          0, 240, DEF_HEIGHT, G_PARAM_READWRITE));
177  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BRIGHTNESS,
178      g_param_spec_int ("brightness", "brightness", "brightness",
179          0, 255, DEF_BRIGHTNESS, G_PARAM_READWRITE));
180  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_WHITEBAL,
181      g_param_spec_int ("whitebal", "whitebal", "whitebal",
182          0, 255, DEF_WHITEBAL, G_PARAM_READWRITE));
183  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CONTRAST,
184      g_param_spec_int ("contrast", "contrast", "contrast",
185          0, 255, DEF_CONTRAST, G_PARAM_READWRITE));
186  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TOP,
187      g_param_spec_int ("top", "top", "top",
188          0, 240, DEF_TOP, G_PARAM_READWRITE));
189  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LEFT,
190      g_param_spec_int ("left", "left", "left",
191          0, 320, DEF_LEFT, G_PARAM_READWRITE));
192  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TRANSFER_SCALE,
193      g_param_spec_int ("transfer_scale", "transfer_scale", "transfer_scale",
194          1, 4, DEF_TRANSFER_SCALE, G_PARAM_READWRITE));
195  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEPTH,
196      g_param_spec_int ("depth", "depth", "depth",
197          4, 6, DEF_DEPTH, G_PARAM_READWRITE));
198  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PORT,
199      g_param_spec_int ("port", "port", "port",
200          0, G_MAXINT, DEF_PORT, G_PARAM_READWRITE));
201  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_AUTOEXP,
202      g_param_spec_enum ("autoexposure", "autoexposure", "autoexposure",
203          GST_TYPE_AUTOEXP_MODE, DEF_AUTOEXP, G_PARAM_READWRITE));
204
205  gobject_class->set_property = gst_qcamsrc_set_property;
206  gobject_class->get_property = gst_qcamsrc_get_property;
207
208  gstelement_class->change_state = gst_qcamsrc_change_state;
209}
210
211static void
212gst_qcamsrc_init (GstQCamSrc * qcamsrc)
213{
214  qcamsrc->srcpad =
215      gst_pad_new_from_template (gst_static_pad_template_get
216      (&gst_qcamsrc_src_factory), "src");
217  gst_element_add_pad (GST_ELEMENT (qcamsrc), qcamsrc->srcpad);
218  gst_pad_set_get_function (qcamsrc->srcpad, gst_qcamsrc_get);
219
220  /* if the destination cannot say what it wants, we give this */
221  qcamsrc->qcam = qc_init ();
222  qcamsrc->qcam->port = DEF_PORT;
223  qc_setwidth (qcamsrc->qcam, DEF_WIDTH);
224  qc_setheight (qcamsrc->qcam, DEF_HEIGHT);
225  qc_setbrightness (qcamsrc->qcam, DEF_BRIGHTNESS);
226  qc_setwhitebal (qcamsrc->qcam, DEF_WHITEBAL);
227  qc_setcontrast (qcamsrc->qcam, DEF_CONTRAST);
228  qc_settop (qcamsrc->qcam, DEF_TOP);
229  qc_setleft (qcamsrc->qcam, DEF_LEFT);
230  qc_settransfer_scale (qcamsrc->qcam, DEF_TRANSFER_SCALE);
231  qc_setbitdepth (qcamsrc->qcam, DEF_DEPTH);
232  qcamsrc->autoexposure = DEF_AUTOEXP;
233  if (qcamsrc->autoexposure != AE_NONE)
234    qcip_set_autoexposure_mode (qcamsrc->autoexposure);
235}
236
237static GstData *
238gst_qcamsrc_get (GstPad * pad)
239{
240  GstQCamSrc *qcamsrc;
241  GstBuffer *buf;
242  scanbuf *scan;
243  guchar *outdata;
244  gint i, frame, scale, convert;
245
246  g_return_val_if_fail (pad != NULL, NULL);
247
248  qcamsrc = GST_QCAMSRC (gst_pad_get_parent (pad));
249
250  scale = qc_gettransfer_scale (qcamsrc->qcam);
251
252  frame = qcamsrc->qcam->width * qcamsrc->qcam->height / (scale * scale);
253
254  buf = gst_buffer_new ();
255  outdata = GST_BUFFER_DATA (buf) = g_malloc0 ((frame * 3) / 2);
256  GST_BUFFER_SIZE (buf) = (frame * 3) / 2;
257
258  qc_set (qcamsrc->qcam);
259  if (!GST_PAD_CAPS (pad)) {
260    gst_pad_try_set_caps (pad, gst_caps_new_simple ("video/x-raw-yuv",
261            "format", GST_TYPE_FOURCC, "I420",
262            "width", G_TYPE_INT, qcamsrc->qcam->width / scale,
263            "height", G_TYPE_INT, qcamsrc->qcam->height / scale,
264            "framerate", G_TYPE_DOUBLE, 10., NULL));
265  }
266  scan = qc_scan (qcamsrc->qcam);
267
268  /* FIXME, this doesn't seem to work... */
269  /*fixdark(qcamsrc->qcam, scan); */
270
271  if (qcamsrc->autoexposure != AE_NONE)
272    qcip_autoexposure (qcamsrc->qcam, scan);
273
274  convert = (qcamsrc->qcam->bpp == 4 ? 4 : 2);
275
276  for (i = frame; i; i--) {
277    outdata[i] = scan[i] << convert;
278  }
279  memset (outdata + frame, 128, frame >> 1);
280  g_free (scan);
281
282  return GST_DATA (buf);
283}
284
285static void
286gst_qcamsrc_set_property (GObject * object, guint prop_id, const GValue * value,
287    GParamSpec * pspec)
288{
289  GstQCamSrc *src;
290
291  /* it's not null if we got it, but it might not be ours */
292  g_return_if_fail (GST_IS_QCAMSRC (object));
293  src = GST_QCAMSRC (object);
294
295  switch (prop_id) {
296    case ARG_WIDTH:
297      qc_setwidth (src->qcam, g_value_get_int (value));
298      break;
299    case ARG_HEIGHT:
300      qc_setheight (src->qcam, g_value_get_int (value));
301      break;
302    case ARG_BRIGHTNESS:
303      qc_setbrightness (src->qcam, g_value_get_int (value));
304      break;
305    case ARG_WHITEBAL:
306      qc_setwhitebal (src->qcam, g_value_get_int (value));
307      break;
308    case ARG_CONTRAST:
309      qc_setcontrast (src->qcam, g_value_get_int (value));
310      break;
311    case ARG_TOP:
312      qc_settop (src->qcam, g_value_get_int (value));
313      break;
314    case ARG_LEFT:
315      qc_setleft (src->qcam, g_value_get_int (value));
316      break;
317    case ARG_TRANSFER_SCALE:
318      qc_settransfer_scale (src->qcam, g_value_get_int (value));
319      break;
320    case ARG_DEPTH:
321      qc_setbitdepth (src->qcam, g_value_get_int (value));
322      break;
323    case ARG_PORT:
324      src->qcam->port = g_value_get_int (value);
325      break;
326    case ARG_AUTOEXP:
327      src->autoexposure = g_value_get_enum (value);
328      if (src->autoexposure != AE_NONE)
329        qcip_set_autoexposure_mode (src->autoexposure);
330      break;
331    default:
332      break;
333  }
334}
335
336static void
337gst_qcamsrc_get_property (GObject * object, guint prop_id, GValue * value,
338    GParamSpec * pspec)
339{
340  GstQCamSrc *src;
341
342  /* it's not null if we got it, but it might not be ours */
343  g_return_if_fail (GST_IS_QCAMSRC (object));
344  src = GST_QCAMSRC (object);
345
346  switch (prop_id) {
347    case ARG_WIDTH:
348      g_value_set_int (value, qc_getwidth (src->qcam));
349      break;
350    case ARG_HEIGHT:
351      g_value_set_int (value, qc_getheight (src->qcam));
352      break;
353    case ARG_BRIGHTNESS:
354      g_value_set_int (value, qc_getbrightness (src->qcam));
355      break;
356    case ARG_WHITEBAL:
357      g_value_set_int (value, qc_getwhitebal (src->qcam));
358      break;
359    case ARG_CONTRAST:
360      g_value_set_int (value, qc_getcontrast (src->qcam));
361      break;
362    case ARG_TOP:
363      g_value_set_int (value, qc_gettop (src->qcam));
364      break;
365    case ARG_LEFT:
366      g_value_set_int (value, qc_getleft (src->qcam));
367      break;
368    case ARG_TRANSFER_SCALE:
369      g_value_set_int (value, qc_gettransfer_scale (src->qcam));
370      break;
371    case ARG_DEPTH:
372      g_value_set_int (value, qc_getbitdepth (src->qcam));
373      break;
374    case ARG_PORT:
375      g_value_set_int (value, src->qcam->port);
376      break;
377    case ARG_AUTOEXP:
378      g_value_set_enum (value, src->autoexposure);
379      break;
380    default:
381      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
382      break;
383  }
384}
385
386static GstElementStateReturn
387gst_qcamsrc_change_state (GstElement * element)
388{
389  g_return_val_if_fail (GST_IS_QCAMSRC (element), FALSE);
390
391  /* if going down into NULL state, close the file if it's open */
392  if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
393    if (GST_FLAG_IS_SET (element, GST_QCAMSRC_OPEN))
394      gst_qcamsrc_close (GST_QCAMSRC (element));
395    /* otherwise (READY or higher) we need to open the sound card */
396  } else {
397    if (!GST_FLAG_IS_SET (element, GST_QCAMSRC_OPEN)) {
398      GST_DEBUG ("opening");
399      if (!gst_qcamsrc_open (GST_QCAMSRC (element))) {
400        GST_DEBUG ("open failed");
401        return GST_STATE_FAILURE;
402      }
403    }
404  }
405
406  if (GST_ELEMENT_CLASS (parent_class)->change_state)
407    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
408
409  return GST_STATE_SUCCESS;
410}
411
412static gboolean
413gst_qcamsrc_open (GstQCamSrc * qcamsrc)
414{
415  if (qc_open (qcamsrc->qcam)) {
416    g_warning ("qcamsrc: Cannot open QuickCam.\n");
417    return FALSE;
418  }
419
420  GST_FLAG_SET (qcamsrc, GST_QCAMSRC_OPEN);
421
422  return TRUE;
423}
424
425static void
426gst_qcamsrc_close (GstQCamSrc * src)
427{
428  qc_close (src->qcam);
429  GST_FLAG_UNSET (src, GST_QCAMSRC_OPEN);
430}
431
432static gboolean
433plugin_init (GstPlugin * plugin)
434{
435  if (!gst_element_register (plugin, "qcamsrc", GST_RANK_NONE,
436          GST_TYPE_QCAMSRC))
437    return FALSE;
438
439  return TRUE;
440}
441
442GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
443    GST_VERSION_MINOR,
444    "qcamsrc",
445    "Read from a QuickCam device",
446    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
Note: See TracBrowser for help on using the repository browser.