1 /* GStreamer |
|
2 * |
|
3 * v4l_calls.c: generic V4L calls |
|
4 * |
|
5 * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net> |
|
6 * |
|
7 * This library is free software; you can redistribute it and/or |
|
8 * modify it under the terms of the GNU Library General Public |
|
9 * License as published by the Free Software Foundation; either |
|
10 * version 2 of the License, or (at your option) any later version. |
|
11 * |
|
12 * This library is distributed in the hope that it will be useful, |
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
15 * Library General Public License for more details. |
|
16 * |
|
17 * You should have received a copy of the GNU Library General Public |
|
18 * License along with this library; if not, write to the |
|
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
20 * Boston, MA 02111-1307, USA. |
|
21 */ |
|
22 |
|
23 #ifdef HAVE_CONFIG_H |
|
24 #include <config.h> |
|
25 #endif |
|
26 |
|
27 #include <sys/types.h> |
|
28 #include <sys/stat.h> |
|
29 #include <fcntl.h> |
|
30 #include <sys/ioctl.h> |
|
31 #include <sys/mman.h> |
|
32 #include <string.h> |
|
33 #include <errno.h> |
|
34 #include <unistd.h> |
|
35 |
|
36 #include <gst/gst.h> |
|
37 #include <gst/interfaces/tuner.h> |
|
38 #include <gst/interfaces/colorbalance.h> |
|
39 |
|
40 #include "v4l_calls.h" |
|
41 #include "gstv4ltuner.h" |
|
42 #include "gstv4lcolorbalance.h" |
|
43 |
|
44 #include "gstv4lsrc.h" |
|
45 /* #include "gstv4lmjpegsrc.h" */ |
|
46 /* #include "gstv4lmjpegsink.h" */ |
|
47 |
|
48 GST_DEBUG_CATEGORY_EXTERN (v4l_debug); |
|
49 #define GST_CAT_DEFAULT v4l_debug |
|
50 |
|
51 static const char *picture_name[] = { |
|
52 "Hue", |
|
53 "Brightness", |
|
54 "Contrast", |
|
55 "Saturation", |
|
56 NULL |
|
57 }; |
|
58 |
|
59 G_GNUC_UNUSED static const char *audio_name[] = { |
|
60 "Volume", |
|
61 "Mute", |
|
62 "Mode", |
|
63 NULL |
|
64 }; |
|
65 |
|
66 static const char *norm_name[] = { |
|
67 "PAL", |
|
68 "NTSC", |
|
69 "SECAM", |
|
70 NULL |
|
71 }; |
|
72 |
|
73 /****************************************************** |
|
74 * gst_v4l_get_capabilities(): |
|
75 * get the device's capturing capabilities |
|
76 * sets v4lelement->vcap and v4lelement->vwin |
|
77 * return value: TRUE on success, FALSE on error |
|
78 ******************************************************/ |
|
79 |
|
80 gboolean |
|
81 gst_v4l_get_capabilities (GstV4lElement * v4lelement) |
|
82 { |
|
83 GST_DEBUG_OBJECT (v4lelement, "getting capabilities"); |
|
84 GST_V4L_CHECK_OPEN (v4lelement); |
|
85 |
|
86 if (ioctl (v4lelement->video_fd, VIDIOCGCAP, &(v4lelement->vcap)) < 0) { |
|
87 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
88 ("error getting capabilities %s of from device %s", |
|
89 g_strerror (errno), v4lelement->videodev)); |
|
90 return FALSE; |
|
91 } |
|
92 |
|
93 if (ioctl (v4lelement->video_fd, VIDIOCGWIN, &(v4lelement->vwin)) < 0) { |
|
94 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
95 ("error getting window properties %s of from device %s", |
|
96 g_strerror (errno), v4lelement->videodev)); |
|
97 return FALSE; |
|
98 } |
|
99 |
|
100 return TRUE; |
|
101 } |
|
102 |
|
103 /****************************************************** |
|
104 * gst_v4l_set_window_properties(): |
|
105 * set the device's capturing parameters (vwin) |
|
106 * return value: TRUE on success, FALSE on error |
|
107 ******************************************************/ |
|
108 |
|
109 gboolean |
|
110 gst_v4l_set_window_properties (GstV4lElement * v4lelement) |
|
111 { |
|
112 struct video_window vwin; |
|
113 |
|
114 GST_DEBUG_OBJECT (v4lelement, "setting window flags 0x%x to device %s", |
|
115 v4lelement->vwin.flags, v4lelement->videodev); |
|
116 GST_V4L_CHECK_OPEN (v4lelement); |
|
117 |
|
118 if (ioctl (v4lelement->video_fd, VIDIOCSWIN, &(v4lelement->vwin)) < 0) { |
|
119 GST_DEBUG_OBJECT (v4lelement, |
|
120 "could not ioctl window properties 0x%x to device %s", |
|
121 v4lelement->vwin.flags, v4lelement->videodev); |
|
122 return FALSE; |
|
123 } |
|
124 |
|
125 /* get it again to make sure we have it correctly */ |
|
126 if (ioctl (v4lelement->video_fd, VIDIOCGWIN, &(vwin)) < 0) { |
|
127 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
128 ("error getting window properties %s of from device %s", |
|
129 g_strerror (errno), v4lelement->videodev)); |
|
130 return FALSE; |
|
131 } |
|
132 if (vwin.flags != v4lelement->vwin.flags) { |
|
133 GST_DEBUG_OBJECT (v4lelement, "set 0x%x but got 0x%x back", |
|
134 v4lelement->vwin.flags, vwin.flags); |
|
135 return FALSE; |
|
136 } |
|
137 |
|
138 return TRUE; |
|
139 } |
|
140 |
|
141 /****************************************************** |
|
142 * gst_v4l_open(): |
|
143 * open the video device (v4lelement->videodev) |
|
144 * return value: TRUE on success, FALSE on error |
|
145 ******************************************************/ |
|
146 |
|
147 gboolean |
|
148 gst_v4l_open (GstV4lElement * v4lelement) |
|
149 { |
|
150 int num; |
|
151 |
|
152 GST_DEBUG_OBJECT (v4lelement, "opening device %s", v4lelement->videodev); |
|
153 GST_V4L_CHECK_NOT_OPEN (v4lelement); |
|
154 GST_V4L_CHECK_NOT_ACTIVE (v4lelement); |
|
155 |
|
156 /* be sure we have a device */ |
|
157 if (!v4lelement->videodev) { |
|
158 GST_ELEMENT_ERROR (v4lelement, RESOURCE, NOT_FOUND, |
|
159 (_("No device specified.")), (NULL)); |
|
160 return FALSE; |
|
161 } |
|
162 |
|
163 /* open the device */ |
|
164 v4lelement->video_fd = open (v4lelement->videodev, O_RDWR); |
|
165 if (!GST_V4L_IS_OPEN (v4lelement)) { |
|
166 if (errno == ENODEV || errno == ENOENT) { |
|
167 GST_ELEMENT_ERROR (v4lelement, RESOURCE, NOT_FOUND, |
|
168 (_("Device \"%s\" does not exist."), v4lelement->videodev), (NULL)); |
|
169 return FALSE; |
|
170 } |
|
171 if (errno == EBUSY) { |
|
172 GST_ELEMENT_ERROR (v4lelement, RESOURCE, BUSY, |
|
173 (_("Device \"%s\" is already being used."), v4lelement->videodev), |
|
174 (NULL)); |
|
175 return FALSE; |
|
176 } |
|
177 GST_ELEMENT_ERROR (v4lelement, RESOURCE, OPEN_READ_WRITE, |
|
178 (_("Could not open device \"%s\" for reading and writing."), |
|
179 v4lelement->videodev), GST_ERROR_SYSTEM); |
|
180 return FALSE; |
|
181 } |
|
182 |
|
183 /* get capabilities */ |
|
184 if (!gst_v4l_get_capabilities (v4lelement)) { |
|
185 close (v4lelement->video_fd); |
|
186 v4lelement->video_fd = -1; |
|
187 return FALSE; |
|
188 } |
|
189 |
|
190 /* device type check */ |
|
191 if ((GST_IS_V4LSRC (v4lelement) && |
|
192 !(v4lelement->vcap.type & VID_TYPE_CAPTURE))) { |
|
193 /* (GST_IS_V4LMJPEGSRC (v4lelement) && */ |
|
194 /* !(v4lelement->vcap.type & VID_TYPE_MJPEG_ENCODER)) || */ |
|
195 /* (GST_IS_V4LMJPEGSINK (v4lelement) && */ |
|
196 /* !(v4lelement->vcap.type & VID_TYPE_MJPEG_DECODER))) { */ |
|
197 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
198 ("Device opened, but wrong type (0x%x)", v4lelement->vcap.type)); |
|
199 close (v4lelement->video_fd); |
|
200 v4lelement->video_fd = -1; |
|
201 return FALSE; |
|
202 } |
|
203 |
|
204 GST_INFO_OBJECT (v4lelement, "Opened device \'%s\' (\'%s\') successfully", |
|
205 v4lelement->vcap.name, v4lelement->videodev); |
|
206 |
|
207 /* norms + inputs, for the tuner interface */ |
|
208 for (num = 0; norm_name[num] != NULL; num++) { |
|
209 GstV4lTunerNorm *v4lnorm = g_object_new (GST_TYPE_V4L_TUNER_NORM, |
|
210 NULL); |
|
211 GstTunerNorm *norm = GST_TUNER_NORM (v4lnorm); |
|
212 |
|
213 norm->label = g_strdup (norm_name[num]); |
|
214 if (num == 1) |
|
215 gst_value_set_fraction (&norm->framerate, 30000, 1001); |
|
216 else |
|
217 gst_value_set_fraction (&norm->framerate, 25, 1); |
|
218 |
|
219 v4lnorm->index = num; |
|
220 v4lelement->norms = g_list_append (v4lelement->norms, (gpointer) norm); |
|
221 } |
|
222 v4lelement->channels = gst_v4l_get_chan_names (v4lelement); |
|
223 |
|
224 for (num = 0; picture_name[num] != NULL; num++) { |
|
225 GstV4lColorBalanceChannel *v4lchannel = |
|
226 g_object_new (GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, NULL); |
|
227 GstColorBalanceChannel *channel = GST_COLOR_BALANCE_CHANNEL (v4lchannel); |
|
228 |
|
229 channel->label = g_strdup (picture_name[num]); |
|
230 channel->min_value = 0; |
|
231 channel->max_value = 65535; |
|
232 v4lchannel->index = num; |
|
233 v4lelement->colors = g_list_append (v4lelement->colors, channel); |
|
234 } |
|
235 |
|
236 GST_DEBUG_OBJECT (v4lelement, "Setting default norm/input"); |
|
237 gst_v4l_set_chan_norm (v4lelement, 0, 0); |
|
238 |
|
239 return TRUE; |
|
240 } |
|
241 |
|
242 |
|
243 /****************************************************** |
|
244 * gst_v4l_close(): |
|
245 * close the video device (v4lelement->video_fd) |
|
246 * return value: TRUE on success, FALSE on error |
|
247 ******************************************************/ |
|
248 |
|
249 gboolean |
|
250 gst_v4l_close (GstV4lElement * v4lelement) |
|
251 { |
|
252 GST_DEBUG_OBJECT (v4lelement, "closing device"); |
|
253 GST_V4L_CHECK_OPEN (v4lelement); |
|
254 GST_V4L_CHECK_NOT_ACTIVE (v4lelement); |
|
255 |
|
256 close (v4lelement->video_fd); |
|
257 v4lelement->video_fd = -1; |
|
258 |
|
259 g_list_foreach (v4lelement->channels, (GFunc) g_object_unref, NULL); |
|
260 g_list_free (v4lelement->channels); |
|
261 v4lelement->channels = NULL; |
|
262 |
|
263 g_list_foreach (v4lelement->norms, (GFunc) g_object_unref, NULL); |
|
264 g_list_free (v4lelement->norms); |
|
265 v4lelement->norms = NULL; |
|
266 |
|
267 g_list_foreach (v4lelement->colors, (GFunc) g_object_unref, NULL); |
|
268 g_list_free (v4lelement->colors); |
|
269 v4lelement->colors = NULL; |
|
270 |
|
271 return TRUE; |
|
272 } |
|
273 |
|
274 |
|
275 /****************************************************** |
|
276 * gst_v4l_get_num_chans() |
|
277 * return value: the number of video input channels |
|
278 ******************************************************/ |
|
279 |
|
280 static gint |
|
281 gst_v4l_get_num_chans (GstV4lElement * v4lelement) |
|
282 { |
|
283 GST_DEBUG_OBJECT (v4lelement, "getting number of channels"); |
|
284 GST_V4L_CHECK_OPEN (v4lelement); |
|
285 |
|
286 return v4lelement->vcap.channels; |
|
287 } |
|
288 |
|
289 |
|
290 /****************************************************** |
|
291 * gst_v4l_get_chan_names() |
|
292 * return value: a GList containing the channel names |
|
293 ******************************************************/ |
|
294 |
|
295 GList * |
|
296 gst_v4l_get_chan_names (GstV4lElement * v4lelement) |
|
297 { |
|
298 struct video_channel vchan; |
|
299 GList *list = NULL; |
|
300 gint i; |
|
301 |
|
302 GST_DEBUG_OBJECT (v4lelement, "getting channel names"); |
|
303 |
|
304 if (!GST_V4L_IS_OPEN (v4lelement)) |
|
305 return NULL; |
|
306 |
|
307 for (i = 0; i < gst_v4l_get_num_chans (v4lelement); i++) { |
|
308 GstV4lTunerChannel *v4lchannel = g_object_new (GST_TYPE_V4L_TUNER_CHANNEL, |
|
309 NULL); |
|
310 GstTunerChannel *channel = GST_TUNER_CHANNEL (v4lchannel); |
|
311 |
|
312 vchan.channel = i; |
|
313 if (ioctl (v4lelement->video_fd, VIDIOCGCHAN, &vchan) < 0) |
|
314 return NULL; /* memleak... */ |
|
315 channel->label = g_strdup (vchan.name); |
|
316 channel->flags = GST_TUNER_CHANNEL_INPUT; |
|
317 v4lchannel->index = i; |
|
318 if (vchan.flags & VIDEO_VC_TUNER) { |
|
319 struct video_tuner vtun; |
|
320 gint n; |
|
321 |
|
322 for (n = 0;; n++) { |
|
323 if (n >= vchan.tuners) { |
|
324 vtun.tuner = 0; /* default */ |
|
325 } else { |
|
326 vtun.tuner = n; |
|
327 if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0) |
|
328 continue; /* no more tuners */ |
|
329 if (strcmp (vtun.name, vchan.name) != 0) { |
|
330 continue; /* not this one */ |
|
331 } |
|
332 } |
|
333 v4lchannel->tuner = n; |
|
334 channel->flags |= GST_TUNER_CHANNEL_FREQUENCY; |
|
335 channel->freq_multiplicator = |
|
336 62.5 * ((vtun.flags & VIDEO_TUNER_LOW) ? 1 : 1000); |
|
337 channel->min_frequency = vtun.rangelow; |
|
338 channel->max_frequency = vtun.rangehigh; |
|
339 channel->min_signal = 0; |
|
340 channel->max_signal = 0xffff; |
|
341 break; |
|
342 } |
|
343 |
|
344 } |
|
345 if (vchan.flags & VIDEO_VC_AUDIO) { |
|
346 struct video_audio vaud; |
|
347 gint n; |
|
348 |
|
349 for (n = 0; n < v4lelement->vcap.audios; n++) { |
|
350 vaud.audio = n; |
|
351 if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vaud) < 0) |
|
352 continue; |
|
353 if (!strcmp (vaud.name, vchan.name)) { |
|
354 v4lchannel->audio = n; |
|
355 channel->flags |= GST_TUNER_CHANNEL_AUDIO; |
|
356 break; |
|
357 } |
|
358 } |
|
359 } |
|
360 list = g_list_append (list, (gpointer) channel); |
|
361 } |
|
362 |
|
363 return list; |
|
364 } |
|
365 |
|
366 |
|
367 /****************************************************** |
|
368 * gst_v4l_get_chan_norm(): |
|
369 * get the currently active video-channel and it's |
|
370 * norm (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO}) |
|
371 * return value: TRUE on success, FALSE on error |
|
372 ******************************************************/ |
|
373 |
|
374 gboolean |
|
375 gst_v4l_get_chan_norm (GstV4lElement * v4lelement, gint * channel, gint * norm) |
|
376 { |
|
377 GST_DEBUG_OBJECT (v4lelement, "getting current channel and norm"); |
|
378 GST_V4L_CHECK_OPEN (v4lelement); |
|
379 |
|
380 if (channel) |
|
381 *channel = v4lelement->vchan.channel; |
|
382 if (norm) |
|
383 *norm = v4lelement->vchan.norm; |
|
384 |
|
385 return TRUE; |
|
386 } |
|
387 |
|
388 |
|
389 /****************************************************** |
|
390 * gst_v4l_set_chan_norm(): |
|
391 * set a new active channel and it's norm |
|
392 * (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO}) |
|
393 * return value: TRUE on success, FALSE on error |
|
394 ******************************************************/ |
|
395 |
|
396 gboolean |
|
397 gst_v4l_set_chan_norm (GstV4lElement * v4lelement, gint channel, gint norm) |
|
398 { |
|
399 GST_DEBUG_OBJECT (v4lelement, "setting channel = %d, norm = %d (%s)", |
|
400 channel, norm, norm_name[norm]); |
|
401 GST_V4L_CHECK_OPEN (v4lelement); |
|
402 //GST_V4L_CHECK_NOT_ACTIVE (v4lelement); |
|
403 |
|
404 v4lelement->vchan.channel = channel; |
|
405 v4lelement->vchan.norm = norm; |
|
406 |
|
407 if (ioctl (v4lelement->video_fd, VIDIOCSCHAN, &(v4lelement->vchan)) < 0) { |
|
408 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
409 ("Error setting the channel/norm settings: %s", g_strerror (errno))); |
|
410 return FALSE; |
|
411 } |
|
412 |
|
413 if (ioctl (v4lelement->video_fd, VIDIOCGCHAN, &(v4lelement->vchan)) < 0) { |
|
414 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
415 ("Error getting the channel/norm settings: %s", g_strerror (errno))); |
|
416 return FALSE; |
|
417 } |
|
418 |
|
419 return TRUE; |
|
420 } |
|
421 |
|
422 |
|
423 /****************************************************** |
|
424 * gst_v4l_get_signal(): |
|
425 * get the current signal |
|
426 * return value: TRUE on success, FALSE on error |
|
427 ******************************************************/ |
|
428 |
|
429 gboolean |
|
430 gst_v4l_get_signal (GstV4lElement * v4lelement, gint tunernum, guint * signal) |
|
431 { |
|
432 struct video_tuner tuner; |
|
433 |
|
434 GST_DEBUG_OBJECT (v4lelement, "getting tuner signal"); |
|
435 GST_V4L_CHECK_OPEN (v4lelement); |
|
436 |
|
437 tuner.tuner = tunernum; |
|
438 if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &tuner) < 0) { |
|
439 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
440 ("Error getting tuner signal: %s", g_strerror (errno))); |
|
441 return FALSE; |
|
442 } |
|
443 |
|
444 *signal = tuner.signal; |
|
445 |
|
446 return TRUE; |
|
447 } |
|
448 |
|
449 |
|
450 /****************************************************** |
|
451 * gst_v4l_get_frequency(): |
|
452 * get the current frequency |
|
453 * return value: TRUE on success, FALSE on error |
|
454 ******************************************************/ |
|
455 |
|
456 gboolean |
|
457 gst_v4l_get_frequency (GstV4lElement * v4lelement, |
|
458 gint tunernum, gulong * frequency) |
|
459 { |
|
460 struct video_tuner vtun; |
|
461 GstTunerChannel *channel; |
|
462 |
|
463 GST_DEBUG_OBJECT (v4lelement, "getting tuner frequency"); |
|
464 GST_V4L_CHECK_OPEN (v4lelement); |
|
465 |
|
466 channel = gst_tuner_get_channel (GST_TUNER (v4lelement)); |
|
467 |
|
468 /* check that this is the current input */ |
|
469 vtun.tuner = tunernum; |
|
470 if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0) |
|
471 return FALSE; |
|
472 if (strcmp (vtun.name, v4lelement->vchan.name)) |
|
473 return FALSE; |
|
474 |
|
475 if (ioctl (v4lelement->video_fd, VIDIOCGFREQ, frequency) < 0) { |
|
476 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
477 ("Error getting tuner frequency: %s", g_strerror (errno))); |
|
478 return FALSE; |
|
479 } |
|
480 |
|
481 *frequency = *frequency * channel->freq_multiplicator; |
|
482 |
|
483 return TRUE; |
|
484 } |
|
485 |
|
486 |
|
487 /****************************************************** |
|
488 * gst_v4l_set_frequency(): |
|
489 * set frequency |
|
490 * return value: TRUE on success, FALSE on error |
|
491 ******************************************************/ |
|
492 |
|
493 gboolean |
|
494 gst_v4l_set_frequency (GstV4lElement * v4lelement, |
|
495 gint tunernum, gulong frequency) |
|
496 { |
|
497 struct video_tuner vtun; |
|
498 GstTunerChannel *channel; |
|
499 |
|
500 GST_DEBUG_OBJECT (v4lelement, "setting tuner frequency to %lu", frequency); |
|
501 GST_V4L_CHECK_OPEN (v4lelement); |
|
502 |
|
503 channel = gst_tuner_get_channel (GST_TUNER (v4lelement)); |
|
504 |
|
505 /* check that this is the current input */ |
|
506 vtun.tuner = tunernum; |
|
507 if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0) |
|
508 return FALSE; |
|
509 if (strcmp (vtun.name, v4lelement->vchan.name)) |
|
510 return FALSE; |
|
511 |
|
512 frequency = frequency / channel->freq_multiplicator; |
|
513 |
|
514 if (ioctl (v4lelement->video_fd, VIDIOCSFREQ, &frequency) < 0) { |
|
515 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
516 ("Error setting tuner frequency: %s", g_strerror (errno))); |
|
517 return FALSE; |
|
518 } |
|
519 |
|
520 return TRUE; |
|
521 } |
|
522 |
|
523 |
|
524 /****************************************************** |
|
525 * gst_v4l_get_picture(): |
|
526 * get a picture value |
|
527 * return value: TRUE on success, FALSE on error |
|
528 ******************************************************/ |
|
529 |
|
530 gboolean |
|
531 gst_v4l_get_picture (GstV4lElement * v4lelement, |
|
532 GstV4lPictureType type, gint * value) |
|
533 { |
|
534 struct video_picture vpic; |
|
535 |
|
536 GST_DEBUG_OBJECT (v4lelement, "getting picture property type %d (%s)", type, |
|
537 picture_name[type]); |
|
538 GST_V4L_CHECK_OPEN (v4lelement); |
|
539 |
|
540 if (ioctl (v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0) { |
|
541 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
542 ("Error getting picture parameters: %s", g_strerror (errno))); |
|
543 return FALSE; |
|
544 } |
|
545 |
|
546 switch (type) { |
|
547 case V4L_PICTURE_HUE: |
|
548 *value = vpic.hue; |
|
549 break; |
|
550 case V4L_PICTURE_BRIGHTNESS: |
|
551 *value = vpic.brightness; |
|
552 break; |
|
553 case V4L_PICTURE_CONTRAST: |
|
554 *value = vpic.contrast; |
|
555 break; |
|
556 case V4L_PICTURE_SATURATION: |
|
557 *value = vpic.colour; |
|
558 break; |
|
559 default: |
|
560 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
561 ("Error getting picture parameters: unknown type %d", type)); |
|
562 return FALSE; |
|
563 } |
|
564 |
|
565 return TRUE; |
|
566 } |
|
567 |
|
568 |
|
569 /****************************************************** |
|
570 * gst_v4l_set_picture(): |
|
571 * set a picture value |
|
572 * return value: TRUE on success, FALSE on error |
|
573 ******************************************************/ |
|
574 |
|
575 gboolean |
|
576 gst_v4l_set_picture (GstV4lElement * v4lelement, |
|
577 GstV4lPictureType type, gint value) |
|
578 { |
|
579 struct video_picture vpic; |
|
580 |
|
581 GST_DEBUG_OBJECT (v4lelement, "setting picture type %d (%s) to value %d", |
|
582 type, picture_name[type], value); |
|
583 GST_V4L_CHECK_OPEN (v4lelement); |
|
584 |
|
585 if (ioctl (v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0) { |
|
586 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
587 ("Error getting picture parameters: %s", g_strerror (errno))); |
|
588 return FALSE; |
|
589 } |
|
590 |
|
591 switch (type) { |
|
592 case V4L_PICTURE_HUE: |
|
593 vpic.hue = value; |
|
594 break; |
|
595 case V4L_PICTURE_BRIGHTNESS: |
|
596 vpic.brightness = value; |
|
597 break; |
|
598 case V4L_PICTURE_CONTRAST: |
|
599 vpic.contrast = value; |
|
600 break; |
|
601 case V4L_PICTURE_SATURATION: |
|
602 vpic.colour = value; |
|
603 break; |
|
604 default: |
|
605 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
606 ("Error setting picture parameters: unknown type %d", type)); |
|
607 return FALSE; |
|
608 } |
|
609 |
|
610 if (ioctl (v4lelement->video_fd, VIDIOCSPICT, &vpic) < 0) { |
|
611 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
612 ("Error setting picture parameters: %s", g_strerror (errno))); |
|
613 return FALSE; |
|
614 } |
|
615 |
|
616 return TRUE; |
|
617 } |
|
618 |
|
619 |
|
620 /****************************************************** |
|
621 * gst_v4l_get_audio(): |
|
622 * get some audio value |
|
623 * return value: TRUE on success, FALSE on error |
|
624 ******************************************************/ |
|
625 |
|
626 gboolean |
|
627 gst_v4l_get_audio (GstV4lElement * v4lelement, |
|
628 gint audionum, GstV4lAudioType type, gint * value) |
|
629 { |
|
630 struct video_audio vau; |
|
631 |
|
632 GST_DEBUG_OBJECT (v4lelement, "getting audio parameter type %d (%s)", type, |
|
633 audio_name[type]); |
|
634 GST_V4L_CHECK_OPEN (v4lelement); |
|
635 |
|
636 vau.audio = audionum; |
|
637 if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0) { |
|
638 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
639 ("Error getting audio parameters: %s", g_strerror (errno))); |
|
640 return FALSE; |
|
641 } |
|
642 |
|
643 switch (type) { |
|
644 case V4L_AUDIO_MUTE: |
|
645 *value = (vau.flags & VIDEO_AUDIO_MUTE); |
|
646 break; |
|
647 case V4L_AUDIO_VOLUME: |
|
648 *value = vau.volume; |
|
649 break; |
|
650 case V4L_AUDIO_MODE: |
|
651 *value = vau.mode; |
|
652 break; |
|
653 default: |
|
654 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
655 ("Error getting audio parameters: unknown type %d", type)); |
|
656 return FALSE; |
|
657 } |
|
658 |
|
659 return TRUE; |
|
660 } |
|
661 |
|
662 |
|
663 /****************************************************** |
|
664 * gst_v4l_set_audio(): |
|
665 * set some audio value |
|
666 * return value: TRUE on success, FALSE on error |
|
667 ******************************************************/ |
|
668 |
|
669 gboolean |
|
670 gst_v4l_set_audio (GstV4lElement * v4lelement, |
|
671 gint audionum, GstV4lAudioType type, gint value) |
|
672 { |
|
673 struct video_audio vau; |
|
674 |
|
675 GST_DEBUG_OBJECT (v4lelement, |
|
676 "setting audio parameter type %d (%s) to value %d", type, |
|
677 audio_name[type], value); |
|
678 GST_V4L_CHECK_OPEN (v4lelement); |
|
679 |
|
680 vau.audio = audionum; |
|
681 if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0) { |
|
682 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
683 ("Error getting audio parameters: %s", g_strerror (errno))); |
|
684 return FALSE; |
|
685 } |
|
686 |
|
687 switch (type) { |
|
688 case V4L_AUDIO_MUTE: |
|
689 if (!(vau.flags & VIDEO_AUDIO_MUTABLE)) { |
|
690 GST_ELEMENT_ERROR (v4lelement, CORE, NOT_IMPLEMENTED, (NULL), |
|
691 ("Error setting audio mute: (un)setting mute is not supported")); |
|
692 return FALSE; |
|
693 } |
|
694 if (value) |
|
695 vau.flags |= VIDEO_AUDIO_MUTE; |
|
696 else |
|
697 vau.flags &= ~VIDEO_AUDIO_MUTE; |
|
698 break; |
|
699 case V4L_AUDIO_VOLUME: |
|
700 if (!(vau.flags & VIDEO_AUDIO_VOLUME)) { |
|
701 GST_ELEMENT_ERROR (v4lelement, CORE, NOT_IMPLEMENTED, (NULL), |
|
702 ("Error setting audio volume: setting volume is not supported")); |
|
703 return FALSE; |
|
704 } |
|
705 vau.volume = value; |
|
706 break; |
|
707 case V4L_AUDIO_MODE: |
|
708 vau.mode = value; |
|
709 break; |
|
710 default: |
|
711 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
712 ("Error setting audio parameters: unknown type %d", type)); |
|
713 return FALSE; |
|
714 } |
|
715 |
|
716 if (ioctl (v4lelement->video_fd, VIDIOCSAUDIO, &vau) < 0) { |
|
717 GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), |
|
718 ("Error setting audio parameters: %s", g_strerror (errno))); |
|
719 return FALSE; |
|
720 } |
|
721 |
|
722 return TRUE; |
|
723 } |
|