Oops, input <-> output confusion
[platform/upstream/gst-plugins-good.git] / sys / v4l2 / v4l2_calls.c
1 /* G-Streamer generic V4L2 element - generic V4L2 calls handling
2  * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
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
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include <sys/mman.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include "v4l2_calls.h"
33 #include "gstv4l2tuner.h"
34 #include "gstv4l2xoverlay.h"
35 #include "gstv4l2colorbalance.h"
36
37 #define DEBUG(format, args...) \
38         GST_DEBUG_OBJECT (\
39                 GST_ELEMENT(v4l2element), \
40                 "V4L2: " format, ##args)
41
42
43 /******************************************************
44  * gst_v4l2_get_capabilities():
45  *   get the device's capturing capabilities
46  * return value: TRUE on success, FALSE on error
47  ******************************************************/
48
49 static gboolean
50 gst_v4l2_get_capabilities (GstV4l2Element *v4l2element)
51 {
52         DEBUG("getting capabilities");
53         GST_V4L2_CHECK_OPEN(v4l2element);
54
55         if (ioctl(v4l2element->video_fd, VIDIOC_QUERYCAP, &(v4l2element->vcap)) < 0) {
56                 gst_element_error(GST_ELEMENT(v4l2element),
57                         "Error getting %s capabilities: %s",
58                         v4l2element->device, g_strerror(errno));
59                 return FALSE;
60         }
61
62         return TRUE;
63 }
64
65
66 /******************************************************
67  * gst_v4l2_empty_lists() and gst_v4l2_fill_lists():
68  *   fill/empty the lists of enumerations
69  * return value: TRUE on success, FALSE on error
70  ******************************************************/
71
72 static gboolean
73 gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
74 {
75         gint n;
76         const GList *pads =
77                 gst_element_get_pad_list (GST_ELEMENT (v4l2element));
78         GstPadDirection dir = GST_PAD_UNKNOWN;
79
80         DEBUG("getting enumerations");
81         GST_V4L2_CHECK_OPEN(v4l2element);
82
83         /* sinks have outputs, all others have inputs */
84         if (pads && g_list_length ((GList *) pads) == 1)
85                 dir = GST_PAD_DIRECTION (GST_PAD (pads->data));
86
87         if (dir != GST_PAD_SINK) {
88         /* and now, the inputs */
89                 for (n=0;;n++) {
90                         struct v4l2_input input;
91                         GstV4l2TunerChannel *v4l2channel;
92                         GstTunerChannel *channel;
93
94                         input.index = n;
95                         if (ioctl(v4l2element->video_fd, VIDIOC_ENUMINPUT,
96                                   &input) < 0) {
97                                 if (errno == EINVAL)
98                                         break; /* end of enumeration */
99                                 else {
100                                         gst_element_error(GST_ELEMENT(v4l2element),
101                                                 "Failed to get no. %d in input enumeration for %s: %s",
102                                                 n, v4l2element->device,
103                                                 g_strerror(errno));
104                                         return FALSE;
105                                 }
106                         }
107
108                         v4l2channel =
109                                 g_object_new(GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
110                         channel = GST_TUNER_CHANNEL(v4l2channel);
111                         channel->label = g_strdup(input.name);
112                         channel->flags = GST_TUNER_CHANNEL_INPUT;
113                         v4l2channel->index = n;
114                         if (input.type == V4L2_INPUT_TYPE_TUNER) {
115                                 struct v4l2_tuner vtun;
116
117                                 v4l2channel->tuner = input.tuner;
118                                 channel->flags |= GST_TUNER_CHANNEL_FREQUENCY;
119
120                                 vtun.index = input.tuner;
121                                 if (ioctl(v4l2element->video_fd, VIDIOC_G_TUNER,
122                                           &vtun) < 0) {
123                                         gst_element_error(GST_ELEMENT(v4l2element),
124                                                 "Failed to get tuner %d settings on %s: %s",
125                                                 input.tuner,
126                                                 v4l2element->device,
127                                                 g_strerror(errno));
128                                         g_object_unref(G_OBJECT(channel));
129                                         return FALSE;
130                                 }
131                                 channel->min_frequency = vtun.rangelow;
132                                 channel->max_frequency = vtun.rangehigh;
133                                 channel->min_signal = 0;
134                                 channel->max_signal = 0xffff;
135                         }
136                         if (input.audioset) {
137                                 /* we take the first. We don't care for
138                                  * the others for now */
139                                 while (!(input.audioset &
140                                          (1<<v4l2channel->audio)))
141                                         v4l2channel->audio++;
142                                 channel->flags |= GST_TUNER_CHANNEL_AUDIO;
143                         }
144
145                         v4l2element->channels =
146                                 g_list_append(v4l2element->channels,
147                                               (gpointer) channel);
148                 }
149         } else {
150                 /* outputs */
151                 for (n=0;;n++) {
152                         struct v4l2_output output;
153                         GstV4l2TunerChannel *v4l2channel;
154                         GstTunerChannel *channel;
155
156                         output.index = n;
157                         if (ioctl(v4l2element->video_fd, VIDIOC_ENUMOUTPUT,
158                                   &output) < 0) {
159                                 if (errno == EINVAL)
160                                         break; /* end of enumeration */
161                                 else {
162                                         gst_element_error(GST_ELEMENT(v4l2element),
163                                                 "Failed to get no. %d in output enumeration for %s: %s",
164                                                 n, v4l2element->device,
165                                                 g_strerror(errno));
166                                         return FALSE;
167                                 }
168                         }
169
170                         v4l2channel = g_object_new(GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
171                         channel = GST_TUNER_CHANNEL(v4l2channel);
172                         channel->label = g_strdup(output.name);
173                         channel->flags = GST_TUNER_CHANNEL_OUTPUT;
174                         v4l2channel->index = n;
175                         if (output.audioset) {
176                                 /* we take the first. We don't care for
177                                  * the others for now */
178                                 while (!(output.audioset &
179                                          (1<<v4l2channel->audio)))
180                                         v4l2channel->audio++;
181                                 channel->flags |= GST_TUNER_CHANNEL_AUDIO;
182                         }
183
184                         v4l2element->channels =
185                                 g_list_append(v4l2element->channels,
186                                               (gpointer) channel);
187                 }
188         }
189
190         /* norms... */
191         for (n=0;;n++) {
192                 struct v4l2_standard standard;
193                 GstV4l2TunerNorm *v4l2norm;
194                 GstTunerNorm *norm;
195
196                 standard.index = n;
197                 if (ioctl(v4l2element->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
198                         if (errno == EINVAL)
199                                 break; /* end of enumeration */
200                         else {
201                                 gst_element_error(GST_ELEMENT(v4l2element),
202                                         "Failed to get no. %d in norm enumeration for %s: %s",
203                                         n, v4l2element->device, g_strerror(errno));
204                                 return FALSE;
205                         }
206                 }
207
208                 v4l2norm = g_object_new(GST_TYPE_V4L2_TUNER_NORM, NULL);
209                 norm = GST_TUNER_NORM (v4l2norm);
210                 norm->label = g_strdup(standard.name);
211                 norm->fps = (gfloat) standard.frameperiod.denominator /
212                                 standard.frameperiod.numerator;
213                 v4l2norm->index = standard.id;
214
215                 v4l2element->norms = g_list_append(v4l2element->norms,
216                                                    (gpointer) norm);
217         }
218
219         /* and lastly, controls+menus (if appropriate) */
220         for (n=V4L2_CID_BASE;;n++) {
221                 struct v4l2_queryctrl control;
222                 GstV4l2ColorBalanceChannel *v4l2channel;
223                 GstColorBalanceChannel *channel;
224
225                 /* hacky... */
226                 if (n == V4L2_CID_LASTP1)
227                         n = V4L2_CID_PRIVATE_BASE;
228
229                 control.id = n;
230                 if (ioctl(v4l2element->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
231                         if (errno == EINVAL) {
232                                 if (n < V4L2_CID_PRIVATE_BASE)
233                                         continue;
234                                 else
235                                         break;
236                         } else {
237                                 gst_element_error(GST_ELEMENT(v4l2element),
238                                         "Failed to get no. %d in control enumeration for %s: %s",
239                                         n, v4l2element->device, g_strerror(errno));
240                                 return FALSE;
241                         }
242                 }
243                 if (control.flags & V4L2_CTRL_FLAG_DISABLED)
244                         continue;
245
246                 switch (n) {
247                         case V4L2_CID_BRIGHTNESS:
248                         case V4L2_CID_CONTRAST:
249                         case V4L2_CID_SATURATION:
250                         case V4L2_CID_HUE:
251                         case V4L2_CID_BLACK_LEVEL:
252                         case V4L2_CID_AUTO_WHITE_BALANCE:
253                         case V4L2_CID_DO_WHITE_BALANCE:
254                         case V4L2_CID_RED_BALANCE:
255                         case V4L2_CID_BLUE_BALANCE:
256                         case V4L2_CID_GAMMA:
257                         case V4L2_CID_EXPOSURE:
258                         case V4L2_CID_AUTOGAIN:
259                         case V4L2_CID_GAIN:
260                                 /* we only handle these for now */
261                                 break;
262                         default:
263                                 DEBUG("ControlID %s (%d) unhandled, FIXME",
264                                       control.name, n);
265                                 control.id++;
266                                 break;
267                 }
268                 if (n != control.id)
269                         continue;
270
271                 v4l2channel = g_object_new(GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL,
272                                            NULL);
273                 channel = GST_COLOR_BALANCE_CHANNEL(v4l2channel);
274                 channel->label = g_strdup(control.name);
275                 v4l2channel->index = n;
276
277 #if 0
278                 if (control.type == V4L2_CTRL_TYPE_MENU) {
279                         struct v4l2_querymenu menu, *mptr;
280                         int i;
281                         menu.id = n;
282                         for (i=0;;i++) {
283                                 menu.index = i;
284                                 if (ioctl(v4l2element->video_fd, VIDIOC_QUERYMENU, &menu) < 0) {
285                                         if (errno == EINVAL)
286                                                 break; /* end of enumeration */
287                                         else {
288                                                 gst_element_error(GST_ELEMENT(v4l2element),
289                                                         "Failed to get no. %d in menu %d enumeration for %s: %s",
290                                                         i, n, v4l2element->device, g_strerror(errno));
291                                                 return FALSE;
292                                         }
293                                 }
294                                 mptr = g_malloc(sizeof(menu));
295                                 memcpy(mptr, &menu, sizeof(menu));
296                                 menus = g_list_append(menus, mptr);
297                         }
298                 }
299                 v4l2element->menus = g_list_append(v4l2element->menus, menus);
300 #endif
301
302                 switch (control.type) {
303                         case V4L2_CTRL_TYPE_INTEGER:
304                                 channel->min_value = control.minimum;
305                                 channel->max_value = control.maximum;
306                                 break;
307                         case V4L2_CTRL_TYPE_BOOLEAN:
308                                 channel->min_value = FALSE;
309                                 channel->max_value = TRUE;
310                                 break;
311                         default:
312                                 channel->min_value =
313                                         channel->max_value = 0;
314                                 break;
315                 }
316
317                 v4l2element->colors = g_list_append(v4l2element->colors,
318                                                     (gpointer) channel);
319         }
320
321         return TRUE;
322 }
323
324
325 static void
326 gst_v4l2_empty_lists (GstV4l2Element *v4l2element)
327 {
328         DEBUG("deleting enumerations");
329
330         g_list_foreach (v4l2element->channels, (GFunc) g_object_unref, NULL);
331         g_list_free (v4l2element->channels);
332         v4l2element->channels = NULL;
333
334         g_list_foreach (v4l2element->norms, (GFunc) g_object_unref, NULL);
335         g_list_free (v4l2element->norms);
336         v4l2element->norms = NULL;
337
338         g_list_foreach (v4l2element->colors, (GFunc) g_object_unref, NULL);
339         g_list_free (v4l2element->colors);
340         v4l2element->colors = NULL;
341 }
342
343
344 /******************************************************
345  * gst_v4l2_open():
346  *   open the video device (v4l2element->device)
347  * return value: TRUE on success, FALSE on error
348  ******************************************************/
349
350 gboolean
351 gst_v4l2_open (GstV4l2Element *v4l2element)
352 {
353         DEBUG("Trying to open device %s", v4l2element->device);
354         GST_V4L2_CHECK_NOT_OPEN(v4l2element);
355         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
356
357         /* be sure we have a device */
358         if (!v4l2element->device)
359                 v4l2element->device = g_strdup("/dev/video");
360
361         /* open the device */
362         v4l2element->video_fd = open(v4l2element->device, O_RDWR);
363         if (!GST_V4L2_IS_OPEN(v4l2element)) {
364                 gst_element_error(GST_ELEMENT(v4l2element),
365                         "Failed to open device %s: %s",
366                         v4l2element->device, g_strerror(errno));
367                 goto error;
368         }
369
370         /* get capabilities */
371         if (!gst_v4l2_get_capabilities(v4l2element)) {
372                 goto error;
373         }
374
375         /* create enumerations */
376         if (!gst_v4l2_fill_lists(v4l2element))
377                 goto error;
378
379         gst_info("Opened device '%s' (%s) successfully\n",
380                 v4l2element->vcap.card, v4l2element->device);
381
382         return TRUE;
383
384 error:
385         if (GST_V4L2_IS_OPEN(v4l2element)) {
386                 /* close device */
387                 close(v4l2element->video_fd);
388                 v4l2element->video_fd = -1;
389         }
390         /* empty lists */
391         gst_v4l2_empty_lists(v4l2element);
392
393         return FALSE;
394 }
395
396
397 /******************************************************
398  * gst_v4l2_close():
399  *   close the video device (v4l2element->video_fd)
400  * return value: TRUE on success, FALSE on error
401  ******************************************************/
402
403 gboolean
404 gst_v4l2_close (GstV4l2Element *v4l2element)
405 {
406         DEBUG("Trying to close %s", v4l2element->device);
407         GST_V4L2_CHECK_OPEN(v4l2element);
408         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
409
410         /* close device */
411         close(v4l2element->video_fd);
412         v4l2element->video_fd = -1;
413
414         /* empty lists */
415         gst_v4l2_empty_lists(v4l2element);
416
417         return TRUE;
418 }
419
420
421 /******************************************************
422  * gst_v4l2_get_norm()
423  *   Get the norm of the current device
424  * return value: TRUE on success, FALSE on error
425  ******************************************************/
426
427 gboolean
428 gst_v4l2_get_norm (GstV4l2Element *v4l2element,
429                    v4l2_std_id    *norm)
430 {
431         DEBUG("getting norm");
432         GST_V4L2_CHECK_OPEN(v4l2element);
433
434         if (ioctl(v4l2element->video_fd, VIDIOC_G_STD, norm) < 0) {
435                 gst_element_error(GST_ELEMENT(v4l2element),
436                         "Failed to get the current norm for device %s: %s",
437                         v4l2element->device, g_strerror(errno));
438                 return FALSE;
439         }
440
441         return TRUE;
442 }
443
444
445 /******************************************************
446  * gst_v4l2_set_norm()
447  *   Set the norm of the current device
448  * return value: TRUE on success, FALSE on error
449  ******************************************************/
450
451 gboolean
452 gst_v4l2_set_norm (GstV4l2Element *v4l2element,
453                    v4l2_std_id     norm)
454 {
455         DEBUG("trying to set norm to %llx", norm);
456         GST_V4L2_CHECK_OPEN(v4l2element);
457         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
458
459         if (ioctl(v4l2element->video_fd, VIDIOC_S_STD, &norm) < 0) {
460                 gst_element_error(GST_ELEMENT(v4l2element),
461                         "Failed to set norm 0x%llx for device %s: %s",
462                         norm, v4l2element->device, g_strerror(errno));
463                 return FALSE;
464         }
465
466         return TRUE;
467 }
468
469
470 /******************************************************
471  * gst_v4l2_get_input()
472  *   Get the input of the current device
473  * return value: TRUE on success, FALSE on error
474  ******************************************************/
475
476 gboolean
477 gst_v4l2_get_input (GstV4l2Element *v4l2element,
478                     gint           *input)
479 {
480         gint n;
481
482         DEBUG("trying to get input");
483         GST_V4L2_CHECK_OPEN(v4l2element);
484
485         if (ioctl(v4l2element->video_fd, VIDIOC_G_INPUT, &n) < 0) {
486                 gst_element_error(GST_ELEMENT(v4l2element),
487                         "Failed to get current input on device %s: %s",
488                         v4l2element->device, g_strerror(errno));
489                 return FALSE;
490         }
491
492         *input = n;
493
494         return TRUE;
495 }
496
497
498 /******************************************************
499  * gst_v4l2_set_input()
500  *   Set the input of the current device
501  * return value: TRUE on success, FALSE on error
502  ******************************************************/
503
504 gboolean
505 gst_v4l2_set_input (GstV4l2Element *v4l2element,
506                     gint            input)
507 {
508         DEBUG("trying to set input to %d", input);
509         GST_V4L2_CHECK_OPEN(v4l2element);
510         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
511
512         if (ioctl(v4l2element->video_fd, VIDIOC_S_INPUT, &input) < 0) {
513                 gst_element_error(GST_ELEMENT(v4l2element),
514                         "Failed to set input %d on device %s: %s",
515                         input, v4l2element->device, g_strerror(errno));
516                 return FALSE;
517         }
518
519         return TRUE;
520 }
521
522
523 /******************************************************
524  * gst_v4l2_get_output()
525  *   Get the output of the current device
526  * return value: TRUE on success, FALSE on error
527  ******************************************************/
528
529 gboolean
530 gst_v4l2_get_output (GstV4l2Element *v4l2element,
531                      gint           *output)
532 {
533         gint n;
534
535         DEBUG("trying to get output");
536         GST_V4L2_CHECK_OPEN(v4l2element);
537
538         if (ioctl(v4l2element->video_fd, VIDIOC_G_OUTPUT, &n) < 0) {
539                 gst_element_error(GST_ELEMENT(v4l2element),
540                         "Failed to get current output on device %s: %s",
541                         v4l2element->device, g_strerror(errno));
542                 return FALSE;
543         }
544
545         *output = n;
546
547         return TRUE;
548 }
549
550
551 /******************************************************
552  * gst_v4l2_set_output()
553  *   Set the output of the current device
554  * return value: TRUE on success, FALSE on error
555  ******************************************************/
556
557 gboolean
558 gst_v4l2_set_output (GstV4l2Element *v4l2element,
559                      gint            output)
560 {
561         DEBUG("trying to set output to %d", output);
562         GST_V4L2_CHECK_OPEN(v4l2element);
563         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
564
565         if (ioctl(v4l2element->video_fd, VIDIOC_S_OUTPUT, &output) < 0) {
566                 gst_element_error(GST_ELEMENT(v4l2element),
567                         "Failed to set output %d on device %s: %s",
568                         output, v4l2element->device, g_strerror(errno));
569                 return FALSE;
570         }
571
572         return TRUE;
573 }
574
575
576 /******************************************************
577  * gst_v4l2_get_frequency():
578  *   get the current frequency
579  * return value: TRUE on success, FALSE on error
580  ******************************************************/
581
582 gboolean
583 gst_v4l2_get_frequency (GstV4l2Element *v4l2element,
584                         gint            tunernum,
585                         gulong         *frequency)
586 {
587         struct v4l2_frequency freq;
588
589         DEBUG("getting current tuner frequency");
590         GST_V4L2_CHECK_OPEN(v4l2element);
591
592         freq.tuner = tunernum;
593         if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
594                 gst_element_error(GST_ELEMENT(v4l2element),
595                         "Failed to get current tuner frequency for device %s: %s",
596                         v4l2element->device, g_strerror(errno));
597                 return FALSE;
598         }
599
600         *frequency = freq.frequency;
601
602         return TRUE;
603 }
604
605
606 /******************************************************
607  * gst_v4l2_set_frequency():
608  *   set frequency
609  * return value: TRUE on success, FALSE on error
610  ******************************************************/
611
612 gboolean
613 gst_v4l2_set_frequency (GstV4l2Element *v4l2element,
614                         gint            tunernum,
615                         gulong          frequency)
616 {
617         struct v4l2_frequency freq;
618
619         DEBUG("setting current tuner frequency to %lu", frequency);
620         GST_V4L2_CHECK_OPEN(v4l2element);
621         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
622
623         freq.tuner = tunernum;
624         /* fill in type - ignore error */
625         ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq);
626         freq.frequency = frequency;
627
628         if (ioctl(v4l2element->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0) {
629                 gst_element_error(GST_ELEMENT(v4l2element),
630                         "Failed to set tuner frequency to %lu for device %s: %s",
631                         frequency, v4l2element->device, g_strerror(errno));
632                 return FALSE;
633         }
634
635         return TRUE;
636 }
637
638
639 /******************************************************
640  * gst_v4l2_signal_strength():
641  *   get the strength of the signal on the current input
642  * return value: TRUE on success, FALSE on error
643  ******************************************************/
644
645 gboolean
646 gst_v4l2_signal_strength (GstV4l2Element *v4l2element,
647                           gint            tunernum,
648                           gulong         *signal_strength)
649 {
650         struct v4l2_tuner tuner;
651
652         DEBUG("trying to get signal strength");
653         GST_V4L2_CHECK_OPEN(v4l2element);
654
655         tuner.index = tunernum;
656         if (ioctl(v4l2element->video_fd, VIDIOC_G_TUNER, &tuner) < 0) {
657                 gst_element_error(GST_ELEMENT(v4l2element),
658                         "Failed to get signal strength for device %s: %s",
659                         v4l2element->device, g_strerror(errno));
660                 return FALSE;
661         }
662
663         *signal_strength = tuner.signal;
664
665         return TRUE;
666 }
667
668
669 /******************************************************
670  * gst_v4l2_get_attribute():
671  *   try to get the value of one specific attribute
672  * return value: TRUE on success, FALSE on error
673  ******************************************************/
674
675 gboolean
676 gst_v4l2_get_attribute  (GstV4l2Element *v4l2element,
677                          int             attribute_num,
678                          int            *value)
679 {
680         struct v4l2_control control;
681
682         GST_V4L2_CHECK_OPEN(v4l2element);
683
684         DEBUG("getting value of attribute %d", attribute_num);
685
686         control.id = attribute_num;
687
688         if (ioctl(v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) {
689                 gst_element_error(GST_ELEMENT(v4l2element),
690                         "Failed to get value for control %d on device %s: %s",
691                         attribute_num, v4l2element->device, g_strerror(errno));
692                 return FALSE;
693         }
694
695         *value = control.value;
696
697         return TRUE;
698 }
699
700
701 /******************************************************
702  * gst_v4l2_set_attribute():
703  *   try to set the value of one specific attribute
704  * return value: TRUE on success, FALSE on error
705  ******************************************************/
706
707 gboolean
708 gst_v4l2_set_attribute  (GstV4l2Element *v4l2element,
709                          int             attribute_num,
710                          const int       value)
711 {
712         struct v4l2_control control;
713
714         GST_V4L2_CHECK_OPEN(v4l2element);
715
716         DEBUG("setting value of attribute %d to %d", attribute_num, value);
717
718         control.id = attribute_num;
719         control.value = value;
720
721         if (ioctl(v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) {
722                 gst_element_error(GST_ELEMENT(v4l2element),
723                         "Failed to set value %d for control %d on device %s: %s",
724                         value, attribute_num, v4l2element->device, g_strerror(errno));
725                 return FALSE;
726         }
727
728         return TRUE;
729 }
730