1 /* G-Streamer generic V4L element - generic V4L calls handling
2 * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
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.
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.
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.
20 #include "v4l_calls.h"
22 static GstElementDetails gst_v4lelement_details = {
23 "Generic video4linux Element",
25 "Generic plugin for handling common video4linux calls",
27 "Ronald Bultje <rbultje@ronald.bitfreak.net>",
31 /* V4lElement signals and args */
55 ARG_DEVICE_IS_CAPTURE,
56 ARG_DEVICE_IS_OVERLAY,
57 ARG_DEVICE_IS_MJPEG_CAPTURE,
58 ARG_DEVICE_IS_MJPEG_PLAYBACK,
59 ARG_DEVICE_IS_MPEG_CAPTURE,
60 ARG_DEVICE_IS_MPEG_PLAYBACK
64 static void gst_v4lelement_class_init (GstV4lElementClass *klass);
65 static void gst_v4lelement_init (GstV4lElement *v4lelement);
66 static void gst_v4lelement_set_property (GObject *object,
70 static void gst_v4lelement_get_property (GObject *object,
74 static GstElementStateReturn gst_v4lelement_change_state (GstElement *element);
75 static gboolean plugin_init (GModule *module,
79 static GstElementClass *parent_class = NULL;
80 //static guint gst_v4lelement_signals[LAST_SIGNAL] = { 0 };
84 gst_v4lelement_get_type (void)
86 static GType v4lelement_type = 0;
88 if (!v4lelement_type) {
89 static const GTypeInfo v4lelement_info = {
90 sizeof(GstV4lElementClass),
93 (GClassInitFunc)gst_v4lelement_class_init,
96 sizeof(GstV4lElement),
98 (GInstanceInitFunc)gst_v4lelement_init,
101 v4lelement_type = g_type_register_static(GST_TYPE_ELEMENT, "GstV4lElement", &v4lelement_info, 0);
103 return v4lelement_type;
109 gst_v4lelement_class_init (GstV4lElementClass *klass)
111 GObjectClass *gobject_class;
112 GstElementClass *gstelement_class;
114 gobject_class = (GObjectClass*)klass;
115 gstelement_class = (GstElementClass*)klass;
117 parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
119 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNEL,
120 g_param_spec_int("channel","channel","channel",
121 G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
122 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNEL_NAMES,
123 g_param_spec_pointer("channel_names","channel_names","channel_names",
125 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NORM,
126 g_param_spec_int("norm","norm","norm",
127 G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
128 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NORM_NAMES,
129 g_param_spec_pointer("norm_names","norm_names","norm_names",
132 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HAS_TUNER,
133 g_param_spec_boolean("has_tuner","has_tuner","has_tuner",
134 0,G_PARAM_READABLE));
135 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FREQUENCY,
136 g_param_spec_ulong("frequency","frequency","frequency",
137 0,G_MAXULONG,0,G_PARAM_READWRITE));
139 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HAS_AUDIO,
140 g_param_spec_boolean("has_audio","has_audio","has_audio",
141 0,G_PARAM_READABLE));
142 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MUTE,
143 g_param_spec_boolean("mute","mute","mute",
144 0,G_PARAM_READWRITE));
145 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VOLUME,
146 g_param_spec_int("volume","volume","volume",
147 G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
148 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MODE,
149 g_param_spec_int("mode","mode","mode",
150 G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
152 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HUE,
153 g_param_spec_int("hue","hue","hue",
154 G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
155 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BRIGHTNESS,
156 g_param_spec_int("brightness","brightness","brightness",
157 G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
158 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CONTRAST,
159 g_param_spec_int("contrast","contrast","contrast",
160 G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
161 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SATURATION,
162 g_param_spec_int("saturation","saturation","saturation",
163 G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
165 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE,
166 g_param_spec_string("device","device","device",
167 NULL, G_PARAM_READWRITE));
168 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_NAME,
169 g_param_spec_string("device_name","device_name","device_name",
170 NULL, G_PARAM_READABLE));
172 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_IS_CAPTURE,
173 g_param_spec_boolean("can_capture","can_capture","can_capture",
174 0,G_PARAM_READABLE));
175 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_IS_OVERLAY,
176 g_param_spec_boolean("has_overlay","has_overlay","has_overlay",
177 0,G_PARAM_READABLE));
179 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_IS_MJPEG_CAPTURE,
180 g_param_spec_boolean("can_capture_mjpeg","can_capture_mjpeg","can_capture_mjpeg",
181 0,G_PARAM_READABLE));
182 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_IS_MJPEG_PLAYBACK,
183 g_param_spec_boolean("can_playback_mjpeg","can_playback_mjpeg","can_playback_mjpeg",
184 0,G_PARAM_READABLE));
186 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_IS_MPEG_CAPTURE,
187 g_param_spec_boolean("can_capture_mpeg","can_capture_mpeg","can_capture_mpeg",
188 0,G_PARAM_READABLE));
189 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_IS_MPEG_PLAYBACK,
190 g_param_spec_boolean("can_playback_mpeg","can_playback_mpeg","can_playback_mpeg",
191 0,G_PARAM_READABLE));
193 gobject_class->set_property = gst_v4lelement_set_property;
194 gobject_class->get_property = gst_v4lelement_get_property;
196 gstelement_class->change_state = gst_v4lelement_change_state;
201 gst_v4lelement_init (GstV4lElement *v4lelement)
203 /* some default values */
204 v4lelement->video_fd = -1;
205 v4lelement->buffer = NULL;
206 v4lelement->videodev = NULL;
208 v4lelement->norm = -1;
209 v4lelement->channel = -1; /* the first channel */
211 v4lelement->frequency = 0;
213 v4lelement->mute = FALSE;
214 v4lelement->volume = -1;
215 v4lelement->mode = -1;
217 v4lelement->brightness = -1;
218 v4lelement->hue = -1;
219 v4lelement->contrast = -1;
220 v4lelement->saturation = -1;
225 gst_v4lelement_set_property (GObject *object,
230 GstV4lElement *v4lelement;
232 /* it's not null if we got it, but it might not be ours */
233 g_return_if_fail(GST_IS_V4LELEMENT(object));
234 v4lelement = GST_V4LELEMENT(object);
239 v4lelement->channel = g_value_get_int(value);
240 if (GST_V4L_IS_OPEN(v4lelement) && !GST_V4L_IS_ACTIVE(v4lelement))
242 if (v4lelement->norm >= VIDEO_MODE_PAL &&
243 v4lelement->norm < VIDEO_MODE_AUTO &&
244 v4lelement->channel >= 0)
245 if (!gst_v4l_set_chan_norm(v4lelement, v4lelement->channel, v4lelement->norm))
250 v4lelement->norm = g_value_get_int(value);
251 if (GST_V4L_IS_OPEN(v4lelement) && !GST_V4L_IS_ACTIVE(v4lelement))
253 if (v4lelement->norm >= VIDEO_MODE_PAL &&
254 v4lelement->norm < VIDEO_MODE_AUTO &&
255 v4lelement->channel >= 0)
256 if (!gst_v4l_set_chan_norm(v4lelement, v4lelement->channel, v4lelement->norm))
261 v4lelement->frequency = g_value_get_ulong(value);
262 if (GST_V4L_IS_OPEN(v4lelement) && !GST_V4L_IS_ACTIVE(v4lelement))
264 if (gst_v4l_has_tuner(v4lelement))
265 if (!gst_v4l_set_frequency(v4lelement, v4lelement->frequency))
270 v4lelement->mute = g_value_get_boolean(value);
271 if (GST_V4L_IS_OPEN(v4lelement))
273 if (gst_v4l_has_audio(v4lelement))
274 if (!gst_v4l_set_audio(v4lelement, V4L_AUDIO_MUTE, v4lelement->mute))
279 v4lelement->mode = g_value_get_int(value);
280 if (GST_V4L_IS_OPEN(v4lelement))
282 if (!gst_v4l_set_audio(v4lelement, V4L_AUDIO_MODE, v4lelement->mute))
287 v4lelement->volume = g_value_get_int(value);
288 if (GST_V4L_IS_OPEN(v4lelement))
290 if (!gst_v4l_set_audio(v4lelement, V4L_AUDIO_VOLUME, v4lelement->volume))
295 v4lelement->hue = g_value_get_int(value);
296 if (GST_V4L_IS_OPEN(v4lelement))
298 if (!gst_v4l_set_picture(v4lelement, V4L_PICTURE_HUE, v4lelement->hue))
303 v4lelement->brightness = g_value_get_int(value);
304 if (GST_V4L_IS_OPEN(v4lelement))
306 if (!gst_v4l_set_picture(v4lelement, V4L_PICTURE_BRIGHTNESS, v4lelement->brightness))
311 v4lelement->contrast = g_value_get_int(value);
312 if (GST_V4L_IS_OPEN(v4lelement))
314 if (!gst_v4l_set_picture(v4lelement, V4L_PICTURE_CONTRAST, v4lelement->contrast))
319 v4lelement->saturation = g_value_get_int(value);
320 if (GST_V4L_IS_OPEN(v4lelement))
322 if (!gst_v4l_set_picture(v4lelement, V4L_PICTURE_SATURATION, v4lelement->saturation))
327 if (GST_V4L_IS_OPEN(v4lelement))
328 break; /* only set when *not* open */
329 if (v4lelement->videodev)
330 g_free(v4lelement->videodev);
331 v4lelement->videodev = g_strdup(g_value_get_string(value));
334 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
341 gst_v4lelement_get_property (GObject *object,
346 GstV4lElement *v4lelement;
351 /* it's not null if we got it, but it might not be ours */
352 g_return_if_fail(GST_IS_V4LELEMENT(object));
353 v4lelement = GST_V4LELEMENT(object);
358 if (GST_V4L_IS_OPEN(v4lelement))
359 gst_v4l_get_chan_norm(v4lelement, &temp_i, NULL);
360 g_value_set_int(value, temp_i);
362 case ARG_CHANNEL_NAMES:
363 if (GST_V4L_IS_OPEN(v4lelement))
364 list = gst_v4l_get_chan_names(v4lelement);
365 g_value_set_pointer(value, (gpointer)list);
368 if (GST_V4L_IS_OPEN(v4lelement))
369 gst_v4l_get_chan_norm(v4lelement, NULL, &temp_i);
370 g_value_set_int(value, temp_i);
373 for (temp_i=0;norm_name[temp_i]!=NULL;temp_i++)
374 list = g_list_append(list, (gpointer)g_strdup(norm_name[temp_i]));
375 g_value_set_pointer(value, (gpointer)list);
378 g_value_set_boolean(value, FALSE);
379 if (GST_V4L_IS_OPEN(v4lelement))
380 if (gst_v4l_has_tuner(v4lelement))
381 g_value_set_boolean(value, TRUE);
384 if (GST_V4L_IS_OPEN(v4lelement))
385 if (gst_v4l_has_tuner(v4lelement))
386 gst_v4l_get_frequency(v4lelement, &temp_ul);
387 g_value_set_ulong(value, temp_ul);
390 g_value_set_boolean(value, FALSE);
391 if (GST_V4L_IS_OPEN(v4lelement))
392 if (gst_v4l_has_audio(v4lelement))
393 g_value_set_boolean(value, TRUE);
396 if (GST_V4L_IS_OPEN(v4lelement))
397 if (gst_v4l_has_audio(v4lelement))
398 gst_v4l_get_audio(v4lelement, V4L_AUDIO_MUTE, &temp_i);
399 g_value_set_boolean(value, temp_i?TRUE:FALSE);
402 if (GST_V4L_IS_OPEN(v4lelement))
403 if (gst_v4l_has_tuner(v4lelement))
404 gst_v4l_get_audio(v4lelement, V4L_AUDIO_MODE, &temp_i);
405 g_value_set_int(value, temp_i);
408 if (GST_V4L_IS_OPEN(v4lelement))
409 if (gst_v4l_has_tuner(v4lelement))
410 gst_v4l_get_audio(v4lelement, V4L_AUDIO_VOLUME, &temp_i);
411 g_value_set_int(value, temp_i);
414 if (GST_V4L_IS_OPEN(v4lelement))
415 gst_v4l_get_picture(v4lelement, V4L_PICTURE_HUE, &temp_i);
416 g_value_set_int(value, temp_i);
419 if (GST_V4L_IS_OPEN(v4lelement))
420 gst_v4l_get_picture(v4lelement, V4L_PICTURE_BRIGHTNESS, &temp_i);
421 g_value_set_int(value, temp_i);
424 if (GST_V4L_IS_OPEN(v4lelement))
425 gst_v4l_get_picture(v4lelement, V4L_PICTURE_CONTRAST, &temp_i);
426 g_value_set_int(value, temp_i);
429 if (GST_V4L_IS_OPEN(v4lelement))
430 gst_v4l_get_picture(v4lelement, V4L_PICTURE_SATURATION, &temp_i);
431 g_value_set_int(value, temp_i);
434 g_value_set_string(value, g_strdup(v4lelement->videodev?v4lelement->videodev:"/dev/video"));
436 case ARG_DEVICE_NAME:
437 if (GST_V4L_IS_OPEN(v4lelement))
438 g_value_set_string(value, g_strdup(v4lelement->vcap.name));
440 g_value_set_string(value, g_strdup("None"));
442 case ARG_DEVICE_IS_CAPTURE:
443 g_value_set_boolean(value, FALSE);
444 if (GST_V4L_IS_OPEN(v4lelement))
445 g_value_set_boolean(value, v4lelement->vcap.type & VID_TYPE_CAPTURE);
447 case ARG_DEVICE_IS_OVERLAY:
448 g_value_set_boolean(value, FALSE);
449 if (GST_V4L_IS_OPEN(v4lelement))
450 g_value_set_boolean(value, v4lelement->vcap.type & VID_TYPE_OVERLAY);
452 case ARG_DEVICE_IS_MJPEG_CAPTURE:
453 g_value_set_boolean(value, FALSE);
454 if (GST_V4L_IS_OPEN(v4lelement))
455 g_value_set_boolean(value, v4lelement->vcap.type & VID_TYPE_MJPEG_ENCODER);
457 case ARG_DEVICE_IS_MJPEG_PLAYBACK:
458 g_value_set_boolean(value, FALSE);
459 if (GST_V4L_IS_OPEN(v4lelement))
460 g_value_set_boolean(value, v4lelement->vcap.type & VID_TYPE_MJPEG_DECODER);
462 case ARG_DEVICE_IS_MPEG_CAPTURE:
463 g_value_set_boolean(value, FALSE);
464 if (GST_V4L_IS_OPEN(v4lelement))
465 g_value_set_boolean(value, v4lelement->vcap.type & VID_TYPE_MPEG_ENCODER);
467 case ARG_DEVICE_IS_MPEG_PLAYBACK:
468 g_value_set_boolean(value, FALSE);
469 if (GST_V4L_IS_OPEN(v4lelement))
470 g_value_set_boolean(value, v4lelement->vcap.type & VID_TYPE_MPEG_DECODER);
473 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
479 static GstElementStateReturn
480 gst_v4lelement_change_state (GstElement *element)
482 GstV4lElement *v4lelement;
484 g_return_val_if_fail(GST_IS_V4LELEMENT(element), GST_STATE_FAILURE);
486 v4lelement = GST_V4LELEMENT(element);
488 /* if going down into NULL state, close the device if it's open
489 * if going to READY, open the device (and set some options)
491 switch (GST_STATE_TRANSITION(element))
493 case GST_STATE_NULL_TO_READY:
497 if (!gst_v4l_open(v4lelement))
498 return GST_STATE_FAILURE;
500 /* now, sync options */
501 if (v4lelement->norm >= VIDEO_MODE_PAL &&
502 v4lelement->norm < VIDEO_MODE_AUTO &&
503 v4lelement->channel >= 0)
505 if (!gst_v4l_set_chan_norm(v4lelement, v4lelement->channel, v4lelement->norm))
506 return GST_STATE_FAILURE;
508 if (v4lelement->frequency > 0 && gst_v4l_has_tuner(v4lelement))
510 if (!gst_v4l_set_frequency(v4lelement, v4lelement->frequency))
511 return GST_STATE_FAILURE;
513 for (n=V4L_AUDIO_VOLUME;n<=V4L_AUDIO_MODE;n++)
517 case V4L_AUDIO_MUTE: temp = v4lelement->mute; break;
518 case V4L_AUDIO_VOLUME: temp = v4lelement->volume; break;
519 case V4L_AUDIO_MODE: temp = v4lelement->mode; break;
521 if (temp >= 0 && gst_v4l_has_audio(v4lelement))
523 if (!gst_v4l_set_audio(v4lelement, n, temp))
524 return GST_STATE_FAILURE;
527 for (n=V4L_PICTURE_HUE;n<=V4L_PICTURE_SATURATION;n++)
531 case V4L_PICTURE_HUE: temp = v4lelement->hue; break;
532 case V4L_PICTURE_BRIGHTNESS: temp = v4lelement->brightness; break;
533 case V4L_PICTURE_SATURATION: temp = v4lelement->saturation; break;
534 case V4L_PICTURE_CONTRAST: temp = v4lelement->contrast; break;
538 if (!gst_v4l_set_picture(v4lelement, n, temp))
539 return GST_STATE_FAILURE;
544 case GST_STATE_READY_TO_NULL:
545 if (!gst_v4l_close(v4lelement))
546 return GST_STATE_FAILURE;
550 if (GST_ELEMENT_CLASS(parent_class)->change_state)
551 return GST_ELEMENT_CLASS(parent_class)->change_state(element);
553 return GST_STATE_SUCCESS;
558 plugin_init (GModule *module,
561 GstElementFactory *factory;
563 /* create an elementfactory for the v4lelement */
564 factory = gst_elementfactory_new("v4lelement", GST_TYPE_V4LELEMENT,
565 &gst_v4lelement_details);
566 g_return_val_if_fail(factory != NULL, FALSE);
567 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
573 GstPluginDesc plugin_desc = {