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