]> git.sesse.net Git - vlc/blob - modules/access/v4l2.c
Fixed compilation warnings.
[vlc] / modules / access / v4l2.c
1 /*****************************************************************************
2  * v4l2.c : Video4Linux2 input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002-2004 the VideoLAN team
5  * $Id: v4l.c 16084 2006-07-19 09:45:02Z zorglub $
6  *
7  * Author: Benjamin Pracht <bigben at videolan dot org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <vlc/vlc.h>
31 #include <vlc_access.h>
32 #include <vlc_demux.h>
33 #include <vlc_input.h>
34 #include <vlc_vout.h>
35
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <sys/time.h>
40 #include <sys/ioctl.h>
41 #include <sys/errno.h>
42
43 #include <asm/types.h>          /* for videodev2.h */
44
45 #include <linux/videodev2.h>
46
47 /*****************************************************************************
48  * Module descriptior
49   *****************************************************************************/
50
51 static int  Open ( vlc_object_t * );
52 static void Close( vlc_object_t * );
53
54 #define DEV_TEXT N_("Device name")
55 #define DEV_LONGTEXT N_( \
56     "Name of the device to use. " \
57     "If you don't specify anything, /dev/video0 will be used.")
58 #define INPUT_TEXT N_( "Input" )
59 #define INPUT_LONGTEXT N_( \
60     "Input of the card to use (Usually, 0 = tuner, " \
61     "1 = composite, 2 = svideo)." )
62
63
64 vlc_module_begin();
65     set_shortname( _("Video4Linux2") );
66     set_description( _("Video4Linux2 input") );
67     set_category( CAT_INPUT );
68     set_subcategory( SUBCAT_INPUT_ACCESS );
69
70     add_string( "v4l2-dev", "/dev/video0", 0, DEV_TEXT, DEV_LONGTEXT,
71                 VLC_FALSE );
72     add_integer( "v4l2-input", 0, NULL, INPUT_TEXT, INPUT_LONGTEXT,
73                 VLC_TRUE );
74
75     add_shortcut( "v4l2" );
76     set_capability( "access_demux", 10 );
77     set_callbacks( Open, Close );
78 vlc_module_end();
79
80 /*****************************************************************************
81  * Access: local prototypes
82  *****************************************************************************/
83
84 static int DemuxMMAP( demux_t * );
85 static int Control( demux_t *, int, va_list );
86
87 static int ProbeDev( demux_t * );
88 static int OpenVideoDev( demux_t * );
89
90 struct demux_sys_t
91 {
92     char *psz_device;
93
94     int i_fd_video;
95
96     struct v4l2_capability dev_cap;
97
98     int i_input;
99     struct v4l2_input *p_inputs;
100     int i_selected_input;
101
102     int i_audio;
103     /* V4L2 devices cannot have more than 32 audio inputs */
104     struct v4l2_audio p_audios[32];
105
106     int i_tuner;
107     struct v4l2_tuner *p_tuners;
108
109     int i_codec;
110     struct v4l2_fmtdesc *p_codecs;
111 };
112
113 /*****************************************************************************
114  * Open: opens v4l device
115  *****************************************************************************
116  *
117  * url: <video device>::::
118  *
119  *****************************************************************************/
120 static int Open( vlc_object_t *p_this )
121 {
122     demux_t     *p_demux = (demux_t*)p_this;
123     demux_sys_t *p_sys;
124
125     /* Only when selected */
126     if( *p_demux->psz_access == '\0' )
127         return VLC_EGENERIC;
128
129     /* Set up p_demux */
130     p_demux->pf_control = Control;
131     p_demux->info.i_update = 0;
132     p_demux->info.i_title = 0;
133     p_demux->info.i_seekpoint = 0;
134
135     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
136     if( p_sys == NULL ) return VLC_ENOMEM;
137     memset( p_sys, 0, sizeof( demux_sys_t ) );
138
139     p_sys->psz_device = var_CreateGetString( p_demux, "v4l2-dev" );
140
141     if( ProbeDev( p_demux ) < 0 ) return VLC_EGENERIC;
142
143     if( OpenVideoDev( p_demux ) < 0 ) return VLC_EGENERIC;
144
145     return VLC_SUCCESS;
146 }
147
148 /*****************************************************************************
149  * Close: close device, free resources
150  *****************************************************************************/
151 static void Close( vlc_object_t *p_this )
152 {
153     demux_t     *p_demux = (demux_t *)p_this;
154     demux_sys_t *p_sys   = p_demux->p_sys;
155
156     if( p_sys->i_fd_video >= 0 ) close( p_sys->i_fd_video );
157
158     if( p_sys->psz_device ) free( p_sys->psz_device );
159     if( p_sys->p_inputs ) free( p_sys->p_inputs );
160     if( p_sys->p_tuners ) free( p_sys->p_tuners );
161     if( p_sys->p_codecs ) free( p_sys->p_codecs );
162
163     free( p_sys );
164 }
165
166 /*****************************************************************************
167  * Control:
168  *****************************************************************************/
169 static int Control( demux_t *p_demux, int i_query, va_list args )
170 {
171     return VLC_EGENERIC;
172 }
173
174 /*****************************************************************************
175  * Demux:
176  *****************************************************************************/
177 static int DemuxMMAP( demux_t *p_demux )
178 {
179     msleep( 40000 );
180     return 1;
181 }
182
183
184 /*****************************************************************************
185  * OpenVideoDev: open and set up the video device and probe for capabilities
186  *****************************************************************************/
187 int OpenVideoDev( demux_t *p_demux )
188 {
189     int i_fd;
190     demux_sys_t *p_sys = p_demux->p_sys;
191
192     if( ( i_fd = open( p_sys->psz_device, O_RDWR ) ) < 0 )
193     {
194         msg_Err( p_demux, "cannot open device (%s)", strerror( errno ) );
195         goto open_failed;
196     }
197
198     p_sys->i_fd_video = i_fd;
199     p_sys->i_selected_input = var_CreateGetInteger( p_demux, "v4l2-input" );
200
201     if( p_sys->i_selected_input > p_sys->i_input )
202     {
203         msg_Warn( p_demux, "invalid input. Using the default one" );
204         p_sys->i_selected_input = 0;
205     }
206
207     if( ioctl( i_fd, VIDIOC_S_INPUT, &p_sys->i_selected_input ) < 0 )
208     {
209        msg_Err( p_demux, "cannot set input (%s)", strerror( errno ) );
210        goto open_failed;
211     }
212
213     if( p_sys->dev_cap.capabilities & V4L2_CAP_STREAMING )
214     {
215         struct v4l2_requestbuffers reqbuf;
216
217         reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
218         reqbuf.memory = V4L2_MEMORY_MMAP;
219         reqbuf.count = 0;
220
221         if( ioctl( i_fd, VIDIOC_REQBUFS, &reqbuf ) < 0 )
222         {
223             msg_Err( p_demux, "cannot initiate I/O operation (%s). "
224                     "Only MMAP is supported at the moment", strerror( errno ) );
225             goto open_failed;
226         }
227         p_demux->pf_demux = DemuxMMAP;
228     }
229     else
230     {
231         msg_Warn( p_demux, "I/O method not supported at the moment" );
232         goto open_failed;
233     }
234
235     return VLC_SUCCESS;
236
237 open_failed:
238     if( i_fd ) close( i_fd );
239     p_sys->i_fd_video = 0;
240     return VLC_EGENERIC;
241
242 }
243
244 /*****************************************************************************
245  * ProbeDev: probe for capabilities
246  *****************************************************************************/
247 int ProbeDev( demux_t *p_demux )
248 {
249     int i_index;
250
251     int i_fd;
252     demux_sys_t *p_sys = p_demux->p_sys;
253
254     if( ( i_fd = open( p_sys->psz_device, O_RDWR ) ) < 0 )
255     {
256         msg_Err( p_demux, "cannot open device (%s)", strerror( errno ) );
257         goto open_failed;
258     }
259
260     /* Get device capabilites */
261
262     if( ioctl( i_fd, VIDIOC_QUERYCAP, &p_sys->dev_cap ) < 0 )
263     {
264         msg_Err( p_demux, "cannot get capabilities (%s)", strerror( errno ) );
265         goto open_failed;
266     }
267
268   msg_Dbg( p_demux, "V4L2 device: %s using driver: %s (version: %u.%u.%u) on %s",
269                             p_sys->dev_cap.card,
270                             p_sys->dev_cap.driver,
271                             (p_sys->dev_cap.version >> 16) & 0xFF,
272                             (p_sys->dev_cap.version >> 8) & 0xFF,
273                             p_sys->dev_cap.version & 0xFF,
274                             p_sys->dev_cap.bus_info );
275
276     msg_Dbg( p_demux, "the device has the capabilities: (%c) Video Capure, "
277                                                        "(%c) Audio, "
278                                                        "(%c) Tuner",
279              ( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE  ? 'X':' '),
280              ( p_sys->dev_cap.capabilities & V4L2_CAP_AUDIO  ? 'X':' '),
281              ( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER  ? 'X':' ') );
282
283     msg_Dbg( p_demux, "supported I/O methods are: (%c) Read/Write, "
284                                                  "(%c) Streaming, "
285                                                  "(%c) Asynchronous",
286             ( p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE ? 'X':' ' ),
287             ( p_sys->dev_cap.capabilities & V4L2_CAP_STREAMING ? 'X':' ' ),
288             ( p_sys->dev_cap.capabilities & V4L2_CAP_ASYNCIO ? 'X':' ' ) );
289
290     /* Now, enumerate all the video inputs. This is useless at the moment
291        since we have no way to present that info to the user except with
292        debug messages */
293
294     if( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE )
295     {
296         while( ioctl( i_fd, VIDIOC_S_INPUT, &p_sys->i_input ) >= 0 )
297         {
298             p_sys->i_input++;
299         }
300
301         p_sys->p_inputs = malloc( p_sys->i_input * sizeof( struct v4l2_input ) );
302         if( !p_sys->p_inputs ) goto open_failed;
303         memset( p_sys->p_inputs, 0, sizeof( struct v4l2_input ) );
304
305         for( i_index = 0; i_index < p_sys->i_input; i_index++ )
306         {
307             p_sys->p_inputs[i_index].index = i_index;
308
309             if( ioctl( i_fd, VIDIOC_ENUMINPUT, &p_sys->p_inputs[i_index] ) )
310             {
311                 msg_Err( p_demux, "cannot get video input characteristics (%s)",
312                                                  strerror( errno ) );
313                 goto open_failed;
314             }
315             msg_Dbg( p_demux, "video input %i (%s) has type: %s",
316                                 i_index,
317                                 p_sys->p_inputs[i_index].name,
318                                 p_sys->p_inputs[i_index].type
319                                         == V4L2_INPUT_TYPE_TUNER ?
320                                         "Tuner adapter" :
321                                         "External analog input" );
322         }
323     }
324
325     /* initialize the structures for the ioctls */
326     for( i_index = 0; i_index < 32; i_index++ )
327     {
328         p_sys->p_audios[i_index].index = i_index;
329     }
330
331     /* Probe audio inputs */
332
333     if( p_sys->dev_cap.capabilities & V4L2_CAP_AUDIO )
334     {
335         while( p_sys->i_audio < 32 &&
336                ioctl( i_fd, VIDIOC_S_AUDIO, &p_sys->p_audios[p_sys->i_audio] ) >= 0 )
337         {
338             if( ioctl( i_fd, VIDIOC_G_AUDIO, &p_sys->p_audios[ p_sys->i_audio] ) < 0 )
339             {
340                 msg_Err( p_demux, "cannot get video input characteristics (%s)",
341                                                  strerror( errno ) );
342                 goto open_failed;
343             }
344
345             msg_Dbg( p_demux, "audio device %i (%s) is %s",
346                                 p_sys->i_audio,
347                                 p_sys->p_audios[p_sys->i_audio].name,
348                                 p_sys->p_audios[p_sys->i_audio].capability &
349                                                     V4L2_AUDCAP_STEREO ?
350                                         "Stereo" : "Mono" );
351
352             p_sys->i_audio++;
353         }
354     }
355
356     if( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER )
357     {
358         struct v4l2_tuner tuner;
359
360         memset( &tuner, 0, sizeof(tuner) );
361         while( ioctl( i_fd, VIDIOC_S_TUNER, &tuner ) >= 0 )
362         {
363             p_sys->i_tuner++;
364             tuner.index = p_sys->i_tuner;
365         }
366
367         p_sys->p_tuners = malloc( p_sys->i_tuner * sizeof( struct v4l2_tuner ) );
368         if( !p_sys->p_tuners ) goto open_failed;
369         memset( p_sys->p_tuners, 0, sizeof( struct v4l2_tuner ) );
370
371         for( i_index = 0; i_index < p_sys->i_tuner; i_index++ )
372         {
373             p_sys->p_tuners[i_index].index = i_index;
374
375             if( ioctl( i_fd, VIDIOC_G_TUNER, &p_sys->p_tuners[i_index] ) )
376             {
377                 msg_Err( p_demux, "cannot get tuner characteristics (%s)",
378                                                  strerror( errno ) );
379                 goto open_failed;
380             }
381             msg_Dbg( p_demux, "tuner %i (%s) has type: %s, "
382                               "frequency range: %.1f %s -> %.1f %s",
383                                 i_index,
384                                 p_sys->p_tuners[i_index].name,
385                                 p_sys->p_tuners[i_index].type
386                                         == V4L2_TUNER_RADIO ?
387                                         "Radio" : "Analog TV",
388                                 p_sys->p_tuners[i_index].rangelow * 62.5,
389                                 p_sys->p_tuners[i_index].capability &
390                                         V4L2_TUNER_CAP_LOW ?
391                                         "Hz" : "kHz",
392                                 p_sys->p_tuners[i_index].rangehigh * 62.5,
393                                 p_sys->p_tuners[i_index].capability &
394                                         V4L2_TUNER_CAP_LOW ?
395                                         "Hz" : "kHz" );
396         }
397     }
398
399     /* Probe for available chromas */
400     if( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE )
401     {
402         struct v4l2_fmtdesc codec;
403
404         i_index = 0;
405         memset( &codec, 0, sizeof(codec) );
406         codec.index = i_index;
407         codec.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
408
409         while( ioctl( i_fd, VIDIOC_ENUM_FMT, &codec ) >= 0 )
410         {
411             i_index++;
412             codec.index = i_index;
413         }
414
415         p_sys->i_codec = i_index;
416
417         p_sys->p_codecs = malloc( p_sys->i_codec * sizeof( struct v4l2_fmtdesc ) );
418         memset( p_sys->p_codecs, 0, p_sys->i_codec * sizeof( struct v4l2_fmtdesc ) ); 
419
420         for( i_index = 0; i_index < p_sys->i_codec; i_index++ )
421         {
422             p_sys->p_codecs[i_index].index = i_index;
423             p_sys->p_codecs[i_index].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
424
425             if( ioctl( i_fd, VIDIOC_ENUM_FMT, &p_sys->p_codecs[i_index] ) < 0 )
426             {
427                 msg_Err( p_demux, "cannot get codec description (%s)", strerror( errno ) );
428                 goto open_failed;
429             }
430
431             msg_Dbg( p_demux, "device supports Codec %s",
432                                 p_sys->p_codecs[i_index].description );
433         }
434     }
435
436
437     if( i_fd >= 0 ) close( i_fd );
438     return VLC_SUCCESS;
439
440 open_failed:
441     
442     if( i_fd >= 0 ) close( i_fd );
443     return VLC_EGENERIC;
444
445 }