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

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