1 /* G-Streamer generic V4L2 element - generic V4L2 calls handling
2 * Copyright (C) 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.
24 #include <sys/types.h>
27 #include <sys/ioctl.h>
31 #include "v4l2_calls.h"
33 #define DEBUG(format, args...) \
34 GST_DEBUG_ELEMENT(GST_CAT_PLUGIN_INFO, \
35 GST_ELEMENT(v4l2element), \
36 "V4L2: " format, ##args)
39 /******************************************************
40 * gst_v4l2_get_capabilities():
41 * get the device's capturing capabilities
42 * return value: TRUE on success, FALSE on error
43 ******************************************************/
46 gst_v4l2_get_capabilities (GstV4l2Element *v4l2element)
48 DEBUG("getting capabilities");
49 GST_V4L2_CHECK_OPEN(v4l2element);
51 if (ioctl(v4l2element->video_fd, VIDIOC_QUERYCAP, &(v4l2element->vcap)) < 0) {
52 gst_element_error(GST_ELEMENT(v4l2element),
53 "Error getting %s capabilities: %s",
54 v4l2element->device, g_strerror(errno));
62 /******************************************************
63 * gst_v4l2_empty_lists() and gst_v4l2_fill_lists():
64 * fill/empty the lists of enumerations
65 * return value: TRUE on success, FALSE on error
66 ******************************************************/
69 gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
73 DEBUG("getting enumerations");
74 GST_V4L2_CHECK_OPEN(v4l2element);
76 /* and now, the inputs */
78 struct v4l2_input input, *inpptr;
80 if (ioctl(v4l2element->video_fd, VIDIOC_ENUMINPUT, &input) < 0) {
82 break; /* end of enumeration */
84 gst_element_error(GST_ELEMENT(v4l2element),
85 "Failed to get no. %d in input enumeration for %s: %s",
86 n, v4l2element->device, g_strerror(errno));
90 inpptr = g_malloc(sizeof(input));
91 memcpy(inpptr, &input, sizeof(input));
92 v4l2element->inputs = g_list_append(v4l2element->inputs, inpptr);
97 struct v4l2_output output, *outptr;
99 if (ioctl(v4l2element->video_fd, VIDIOC_ENUMOUTPUT, &output) < 0) {
101 break; /* end of enumeration */
103 gst_element_error(GST_ELEMENT(v4l2element),
104 "Failed to get no. %d in output enumeration for %s: %s",
105 n, v4l2element->device, g_strerror(errno));
109 outptr = g_malloc(sizeof(output));
110 memcpy(outptr, &output, sizeof(output));
111 v4l2element->outputs = g_list_append(v4l2element->outputs, outptr);
116 struct v4l2_standard standard, *stdptr;
118 if (ioctl(v4l2element->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
120 break; /* end of enumeration */
122 gst_element_error(GST_ELEMENT(v4l2element),
123 "Failed to get no. %d in norm enumeration for %s: %s",
124 n, v4l2element->device, g_strerror(errno));
128 stdptr = g_malloc(sizeof(standard));
129 memcpy(stdptr, &standard, sizeof(standard));
130 v4l2element->norms = g_list_append(v4l2element->norms, stdptr);
133 /* and lastly, controls+menus (if appropriate) */
134 for (n=V4L2_CID_BASE;;n++) {
135 struct v4l2_queryctrl control, *ctrlptr;
138 if (n == V4L2_CID_LASTP1)
139 n = V4L2_CID_PRIVATE_BASE;
141 if (ioctl(v4l2element->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
142 if (errno == EINVAL) {
143 if (n < V4L2_CID_PRIVATE_BASE)
148 gst_element_error(GST_ELEMENT(v4l2element),
149 "Failed to get no. %d in control enumeration for %s: %s",
150 n, v4l2element->device, g_strerror(errno));
154 if (control.flags & V4L2_CTRL_FLAG_DISABLED)
156 ctrlptr = g_malloc(sizeof(control));
157 memcpy(ctrlptr, &control, sizeof(control));
158 v4l2element->controls = g_list_append(v4l2element->controls, ctrlptr);
159 if (control.type == V4L2_CTRL_TYPE_MENU) {
160 struct v4l2_querymenu menu, *mptr;
165 if (ioctl(v4l2element->video_fd, VIDIOC_QUERYMENU, &menu) < 0) {
167 break; /* end of enumeration */
169 gst_element_error(GST_ELEMENT(v4l2element),
170 "Failed to get no. %d in menu %d enumeration for %s: %s",
171 i, n, v4l2element->device, g_strerror(errno));
175 mptr = g_malloc(sizeof(menu));
176 memcpy(mptr, &menu, sizeof(menu));
177 menus = g_list_append(menus, mptr);
180 v4l2element->menus = g_list_append(v4l2element->menus, menus);
188 gst_v4l2_empty_lists (GstV4l2Element *v4l2element)
190 DEBUG("deleting enumerations");
193 while (g_list_length(v4l2element->inputs) > 0) {
194 gpointer data = g_list_nth_data(v4l2element->inputs, 0);
195 v4l2element->inputs = g_list_remove(v4l2element->inputs, data);
198 while (g_list_length(v4l2element->outputs) > 0) {
199 gpointer data = g_list_nth_data(v4l2element->outputs, 0);
200 v4l2element->outputs = g_list_remove(v4l2element->outputs, data);
203 while (g_list_length(v4l2element->norms) > 0) {
204 gpointer data = g_list_nth_data(v4l2element->norms, 0);
205 v4l2element->norms = g_list_remove(v4l2element->norms, data);
208 while (g_list_length(v4l2element->controls) > 0) {
209 gpointer data = g_list_nth_data(v4l2element->controls, 0);
210 v4l2element->controls = g_list_remove(v4l2element->controls, data);
213 v4l2element->menus = g_list_remove_all(v4l2element->menus, NULL);
214 while (g_list_length(v4l2element->menus) > 0) {
215 GList *items = (GList *) g_list_nth_data(v4l2element->menus, 0);
216 v4l2element->inputs = g_list_remove(v4l2element->inputs, items);
217 while (g_list_length(items) > 0) {
218 gpointer data = g_list_nth_data(v4l2element->menus, 0);
219 items = g_list_remove(items, data);
226 /******************************************************
228 * open the video device (v4l2element->device)
229 * return value: TRUE on success, FALSE on error
230 ******************************************************/
233 gst_v4l2_open (GstV4l2Element *v4l2element)
235 DEBUG("Trying to open device %s", v4l2element->device);
236 GST_V4L2_CHECK_NOT_OPEN(v4l2element);
237 GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
239 /* be sure we have a device */
240 if (!v4l2element->device)
241 v4l2element->device = g_strdup("/dev/video");
243 /* open the device */
244 v4l2element->video_fd = open(v4l2element->device, O_RDWR);
245 if (!GST_V4L2_IS_OPEN(v4l2element)) {
246 gst_element_error(GST_ELEMENT(v4l2element),
247 "Failed to open device %s: %s",
248 v4l2element->device, g_strerror(errno));
252 /* get capabilities */
253 if (!gst_v4l2_get_capabilities(v4l2element)) {
257 /* create enumerations */
258 if (!gst_v4l2_fill_lists(v4l2element))
261 gst_info("Opened device '%s' (%s) successfully\n",
262 v4l2element->vcap.card, v4l2element->device);
267 if (GST_V4L2_IS_OPEN(v4l2element)) {
269 close(v4l2element->video_fd);
270 v4l2element->video_fd = -1;
273 gst_v4l2_empty_lists(v4l2element);
279 /******************************************************
281 * close the video device (v4l2element->video_fd)
282 * return value: TRUE on success, FALSE on error
283 ******************************************************/
286 gst_v4l2_close (GstV4l2Element *v4l2element)
288 DEBUG("Trying to close %s", v4l2element->device);
289 GST_V4L2_CHECK_OPEN(v4l2element);
290 GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
293 close(v4l2element->video_fd);
294 v4l2element->video_fd = -1;
297 gst_v4l2_empty_lists(v4l2element);
303 /******************************************************
304 * gst_v4l2_get_norm()
305 * Get the norm of the current device
306 * return value: TRUE on success, FALSE on error
307 ******************************************************/
310 gst_v4l2_get_norm (GstV4l2Element *v4l2element,
316 DEBUG("getting norm");
317 GST_V4L2_CHECK_OPEN(v4l2element);
319 if (ioctl(v4l2element->video_fd, VIDIOC_G_STD, &std_id) < 0) {
320 gst_element_error(GST_ELEMENT(v4l2element),
321 "Failed to get the current norm for device %s: %s",
322 v4l2element->device, g_strerror(errno));
326 /* try to find out what norm number this actually is */
327 for (n=0;n<g_list_length(v4l2element->norms);n++) {
328 struct v4l2_standard *stdptr = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, n);
329 if (stdptr->id == std_id) {
335 gst_element_error(GST_ELEMENT(v4l2element),
336 "Failed to find norm '%llu' in our list of available norms for device %s",
337 std_id, v4l2element->device);
342 /******************************************************
343 * gst_v4l2_set_norm()
344 * Set the norm of the current device
345 * return value: TRUE on success, FALSE on error
346 ******************************************************/
349 gst_v4l2_set_norm (GstV4l2Element *v4l2element,
352 struct v4l2_standard *standard;
354 DEBUG("trying to set norm to %d", norm);
355 GST_V4L2_CHECK_OPEN(v4l2element);
356 GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
358 if (norm < 0 || norm >= g_list_length(v4l2element->norms)) {
359 gst_element_error(GST_ELEMENT(v4l2element),
360 "Invalid norm number %d (%d-%d)",
361 norm, 0, g_list_length(v4l2element->norms));
365 standard = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, norm);
367 if (ioctl(v4l2element->video_fd, VIDIOC_S_STD, &standard->id) < 0) {
368 gst_element_error(GST_ELEMENT(v4l2element),
369 "Failed to set norm '%s' (%llu) for device %s: %s",
370 standard->name, standard->id, v4l2element->device, g_strerror(errno));
378 /******************************************************
379 * gst_v4l2_get_norm_names()
380 * Get the list of available norms
381 * return value: the list
382 ******************************************************/
385 gst_v4l2_get_norm_names (GstV4l2Element *v4l2element)
390 DEBUG("getting a list of norm names");
392 for (n=0;n<g_list_length(v4l2element->norms);n++) {
393 struct v4l2_standard *standard = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, n);
394 names = g_list_append(names, g_strdup(standard->name));
401 /******************************************************
402 * gst_v4l2_get_input()
403 * Get the input of the current device
404 * return value: TRUE on success, FALSE on error
405 ******************************************************/
408 gst_v4l2_get_input (GstV4l2Element *v4l2element,
413 DEBUG("trying to get input");
414 GST_V4L2_CHECK_OPEN(v4l2element);
416 if (ioctl(v4l2element->video_fd, VIDIOC_G_INPUT, &n) < 0) {
417 gst_element_error(GST_ELEMENT(v4l2element),
418 "Failed to get current input on device %s: %s",
419 v4l2element->device, g_strerror(errno));
429 /******************************************************
430 * gst_v4l2_set_input()
431 * Set the input of the current device
432 * return value: TRUE on success, FALSE on error
433 ******************************************************/
436 gst_v4l2_set_input (GstV4l2Element *v4l2element,
439 DEBUG("trying to set input to %d", input);
440 GST_V4L2_CHECK_OPEN(v4l2element);
441 GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
443 if (input < 0 || input >= g_list_length(v4l2element->inputs)) {
444 gst_element_error(GST_ELEMENT(v4l2element),
445 "Invalid input number %d (%d-%d)",
446 input, 0, g_list_length(v4l2element->inputs));
450 if (ioctl(v4l2element->video_fd, VIDIOC_S_INPUT, &input) < 0) {
451 gst_element_error(GST_ELEMENT(v4l2element),
452 "Failed to set input %d on device %s: %s",
453 input, v4l2element->device, g_strerror(errno));
461 /******************************************************
462 * gst_v4l2_get_input_names()
463 * Get the list of available input channels
464 * return value: the list
465 ******************************************************/
468 gst_v4l2_get_input_names (GstV4l2Element *v4l2element)
473 DEBUG("getting a list of input names");
475 for (n=0;n<g_list_length(v4l2element->inputs);n++) {
476 struct v4l2_input *input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, n);
477 names = g_list_append(names, g_strdup(input->name));
484 /******************************************************
485 * gst_v4l2_get_output()
486 * Get the output of the current device
487 * return value: TRUE on success, FALSE on error
488 ******************************************************/
491 gst_v4l2_get_output (GstV4l2Element *v4l2element,
496 DEBUG("trying to get output");
497 GST_V4L2_CHECK_OPEN(v4l2element);
499 if (ioctl(v4l2element->video_fd, VIDIOC_G_OUTPUT, &n) < 0) {
500 gst_element_error(GST_ELEMENT(v4l2element),
501 "Failed to get current output on device %s: %s",
502 v4l2element->device, g_strerror(errno));
512 /******************************************************
513 * gst_v4l2_set_output()
514 * Set the output of the current device
515 * return value: TRUE on success, FALSE on error
516 ******************************************************/
519 gst_v4l2_set_output (GstV4l2Element *v4l2element,
522 DEBUG("trying to set output to %d", output);
523 GST_V4L2_CHECK_OPEN(v4l2element);
524 GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
526 if (output < 0 || output >= g_list_length(v4l2element->outputs)) {
527 gst_element_error(GST_ELEMENT(v4l2element),
528 "Invalid output number %d (%d-%d)",
529 output, 0, g_list_length(v4l2element->outputs));
533 if (ioctl(v4l2element->video_fd, VIDIOC_S_OUTPUT, &output) < 0) {
534 gst_element_error(GST_ELEMENT(v4l2element),
535 "Failed to set output %d on device %s: %s",
536 output, v4l2element->device, g_strerror(errno));
544 /******************************************************
545 * gst_v4l2_get_output_names()
546 * Get the list of available output channels
547 * return value: the list, or NULL on error
548 ******************************************************/
551 gst_v4l2_get_output_names (GstV4l2Element *v4l2element)
556 DEBUG("getting a list of output names");
558 for (n=0;n<g_list_length(v4l2element->outputs);n++) {
559 struct v4l2_output *output = (struct v4l2_output *) g_list_nth_data(v4l2element->outputs, n);
560 names = g_list_append(names, g_strdup(output->name));
567 /******************************************************
568 * gst_v4l_has_tuner():
569 * Check whether the device has a tuner
570 * return value: TRUE if it has a tuner, else FALSE
571 ******************************************************/
574 gst_v4l2_has_tuner (GstV4l2Element *v4l2element,
578 struct v4l2_input *input;
580 DEBUG("detecting whether device has a tuner");
581 GST_V4L2_CHECK_OPEN(v4l2element);
583 if (!gst_v4l2_get_input(v4l2element, &input_num))
586 input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num);
588 if (input->type == V4L2_INPUT_TYPE_TUNER &&
589 v4l2element->vcap.capabilities & V4L2_CAP_TUNER) {
590 *tuner_num = input->tuner;
597 /******************************************************
598 * gst_v4l_get_frequency():
599 * get the current frequency
600 * return value: TRUE on success, FALSE on error
601 ******************************************************/
604 gst_v4l2_get_frequency (GstV4l2Element *v4l2element,
607 struct v4l2_frequency freq;
609 DEBUG("getting current tuner frequency");
610 GST_V4L2_CHECK_OPEN(v4l2element);
612 if (!gst_v4l2_has_tuner(v4l2element, &freq.tuner))
617 if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
618 gst_element_error(GST_ELEMENT(v4l2element),
619 "Failed to get current tuner frequency for device %s: %s",
620 v4l2element->device, g_strerror(errno));
624 *frequency = freq.frequency;
630 /******************************************************
631 * gst_v4l_set_frequency():
633 * return value: TRUE on success, FALSE on error
634 ******************************************************/
637 gst_v4l2_set_frequency (GstV4l2Element *v4l2element,
640 struct v4l2_frequency freq;
642 DEBUG("setting current tuner frequency to %lu", frequency);
643 GST_V4L2_CHECK_OPEN(v4l2element);
644 GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
646 if (!gst_v4l2_has_tuner(v4l2element, &freq.tuner))
649 freq.frequency = frequency;
652 if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
653 gst_element_error(GST_ELEMENT(v4l2element),
654 "Failed to set tuner frequency to %lu for device %s: %s",
655 frequency, v4l2element->device, g_strerror(errno));
663 /******************************************************
664 * gst_v4l_signal_strength():
665 * get the strength of the signal on the current input
666 * return value: TRUE on success, FALSE on error
667 ******************************************************/
670 gst_v4l2_signal_strength (GstV4l2Element *v4l2element,
671 gulong *signal_strength)
673 struct v4l2_tuner tuner;
675 DEBUG("trying to get signal strength");
676 GST_V4L2_CHECK_OPEN(v4l2element);
678 if (ioctl(v4l2element->video_fd, VIDIOC_G_TUNER, &tuner) < 0) {
679 gst_element_error(GST_ELEMENT(v4l2element),
680 "Failed to get signal strength for device %s: %s",
681 v4l2element->device, g_strerror(errno));
685 *signal_strength = tuner.signal;
691 /******************************************************
692 * gst_v4l_has_audio():
693 * Check whether the device has audio capabilities
694 * return value: TRUE if it has a tuner, else FALSE
695 ******************************************************/
698 gst_v4l2_has_audio (GstV4l2Element *v4l2element)
701 struct v4l2_input *input;
703 DEBUG("detecting whether device has audio");
704 GST_V4L2_CHECK_OPEN(v4l2element);
706 if (!gst_v4l2_get_input(v4l2element, &input_num))
709 input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num);
711 return (input->audioset != 0);
715 /******************************************************
716 * gst_v4l_get_attributes():
717 * get a list of attributes available on this device
718 * return value: the list
719 ******************************************************/
722 gst_v4l2_get_attributes (GstV4l2Element *v4l2element)
727 DEBUG("getting a list of available attributes");
729 for (i=0;i<g_list_length(v4l2element->controls);i++) {
730 struct v4l2_queryctrl *control = (struct v4l2_queryctrl *) g_list_nth_data(v4l2element->controls, i);
731 GstV4l2Attribute* attribute = g_malloc(sizeof(GstV4l2Attribute));
732 attribute->name = g_strdup(control->name);
733 attribute->index = i;
734 attribute->list_items = NULL;
735 attribute->val_type = control->type;
736 if (control->type == V4L2_CTRL_TYPE_MENU) {
739 GList *menus = (GList *) g_list_nth_data(v4l2element->menus, i);
740 for (n=0;n<g_list_length(menus);n++) {
741 struct v4l2_querymenu *menu = g_list_nth_data(menus, n);
742 attribute->list_items = g_list_append(attribute->list_items,
743 g_strdup(menu->name));
746 switch (control->id) {
747 case V4L2_CID_BRIGHTNESS:
748 case V4L2_CID_CONTRAST:
749 case V4L2_CID_SATURATION:
751 case V4L2_CID_BLACK_LEVEL:
752 case V4L2_CID_AUTO_WHITE_BALANCE:
753 case V4L2_CID_DO_WHITE_BALANCE:
754 case V4L2_CID_RED_BALANCE:
755 case V4L2_CID_BLUE_BALANCE:
757 case V4L2_CID_EXPOSURE:
758 case V4L2_CID_AUTOGAIN:
762 case V4L2_CID_HCENTER:
763 case V4L2_CID_VCENTER:
764 attribute->type = GST_V4L2_ATTRIBUTE_TYPE_VIDEO;
766 case V4L2_CID_AUDIO_VOLUME:
767 case V4L2_CID_AUDIO_BALANCE:
768 case V4L2_CID_AUDIO_BASS:
769 case V4L2_CID_AUDIO_TREBLE:
770 case V4L2_CID_AUDIO_MUTE:
771 case V4L2_CID_AUDIO_LOUDNESS:
772 attribute->type = GST_V4L2_ATTRIBUTE_TYPE_AUDIO;
775 attribute->type = GST_V4L2_ATTRIBUTE_TYPE_OTHER;
778 gst_v4l2_get_attribute(v4l2element, i, &attribute->value);
779 attribute->min = control->minimum;
780 attribute->max = control->maximum;
787 /******************************************************
788 * gst_v4l_get_attribute():
789 * try to get the value of one specific attribute
790 * return value: TRUE on success, FALSE on error
791 ******************************************************/
794 gst_v4l2_get_attribute (GstV4l2Element *v4l2element,
798 struct v4l2_control control;
800 DEBUG("getting value of attribute %d", attribute_num);
801 GST_V4L2_CHECK_OPEN(v4l2element);
803 if (attribute_num < 0 || attribute_num >= g_list_length(v4l2element->controls)) {
804 gst_element_error(GST_ELEMENT(v4l2element),
805 "Invalid control ID %d", attribute_num);
809 control.id = attribute_num;
811 if (ioctl(v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) {
812 gst_element_error(GST_ELEMENT(v4l2element),
813 "Failed to get value for control %d on device %s: %s",
814 attribute_num, v4l2element->device, g_strerror(errno));
818 *value = control.value;
824 /******************************************************
825 * gst_v4l_set_attribute():
826 * try to set the value of one specific attribute
827 * return value: TRUE on success, FALSE on error
828 ******************************************************/
831 gst_v4l2_set_attribute (GstV4l2Element *v4l2element,
835 struct v4l2_control control;
837 DEBUG("setting value of attribute %d to %d", attribute_num, value);
838 GST_V4L2_CHECK_OPEN(v4l2element);
840 if (attribute_num < 0 || attribute_num >= g_list_length(v4l2element->controls)) {
841 gst_element_error(GST_ELEMENT(v4l2element),
842 "Invalid control ID %d", attribute_num);
846 control.id = attribute_num;
847 control.value = value;
849 if (ioctl(v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) {
850 gst_element_error(GST_ELEMENT(v4l2element),
851 "Failed to set value %d for control %d on device %s: %s",
852 value, attribute_num, v4l2element->device, g_strerror(errno));