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