* Some more debug
[vlc.git] / 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/input.h>
32 #include <vlc/vout.h>
33
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <sys/time.h>
38 #include <sys/ioctl.h>
39 #include <sys/errno.h>
40
41 #include <asm/types.h>          /* for videodev2.h */
42
43 #include <linux/videodev2.h>
44
45 /*****************************************************************************
46  * Module descriptior
47   *****************************************************************************/
48
49 static int  Open ( vlc_object_t * );
50 static void Close( vlc_object_t * );
51
52 #define DEV_TEXT N_("Device name")
53 #define DEV_LONGTEXT N_( \
54     "Name of the device to use. " \
55     "If you don't specify anything, /dev/video0 will be used.")
56
57
58 vlc_module_begin();
59     set_shortname( _("Video4Linux2") );
60     set_description( _("Video4Linux2 input") );
61     set_category( CAT_INPUT );
62     set_subcategory( SUBCAT_INPUT_ACCESS );
63
64     add_string( "v4l2-dev", "/dev/video0", 0, DEV_TEXT, DEV_LONGTEXT,
65                 VLC_FALSE );
66
67     add_shortcut( "v4l2" );
68     set_capability( "access_demux", 10 );
69     set_callbacks( Open, Close );
70 vlc_module_end();
71
72 /*****************************************************************************
73  * Access: local prototypes
74  *****************************************************************************/
75
76 static int Demux  ( demux_t * );
77 static int Control( demux_t *, int, va_list );
78
79 static int OpenDev( demux_t * );
80
81 struct demux_sys_t
82 {
83     char *psz_device;
84
85     int i_fd_video;
86
87     struct v4l2_capability dev_cap;
88
89     int i_input;
90     struct v4l2_input *p_inputs;
91
92     int i_audio;
93     /* V4L2 devices cannot have more than 32 audio inputs */
94     struct v4l2_audio p_audios[32];
95
96     int i_tuner;
97     struct v4l2_tuner *p_tuners;
98 };
99
100 /*****************************************************************************
101  * Open: opens v4l device
102  *****************************************************************************
103  *
104  * url: <video device>::::
105  *
106  *****************************************************************************/
107 static int Open( vlc_object_t *p_this )
108 {
109     demux_t     *p_demux = (demux_t*)p_this;
110     demux_sys_t *p_sys;
111     demux_sys_t sys;
112
113     /* Set up p_demux */
114     p_demux->pf_demux = Demux;
115     p_demux->pf_control = Control;
116     p_demux->info.i_update = 0;
117     p_demux->info.i_title = 0;
118     p_demux->info.i_seekpoint = 0;
119
120     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
121     if( p_sys == NULL ) return VLC_ENOMEM;
122     memset( p_sys, 0, sizeof( demux_sys_t ) );
123
124     p_sys->psz_device = var_CreateGetString( p_demux, "v4l2-dev" );
125
126     if( OpenDev( p_demux ) < 0 ) return VLC_EGENERIC;
127
128     return VLC_SUCCESS;
129 }
130
131 /*****************************************************************************
132  * Close: close device, free resources
133  *****************************************************************************/
134 static void Close( vlc_object_t *p_this )
135 {
136     demux_t     *p_demux = (demux_t *)p_this;
137     demux_sys_t *p_sys   = p_demux->p_sys;
138
139     if( p_sys->psz_device ) free( p_sys->psz_device );
140     if( p_sys->p_inputs ) free( p_sys->p_inputs );
141
142     free( p_sys );
143 }
144
145 /*****************************************************************************
146  * Control:
147  *****************************************************************************/
148 static int Control( demux_t *p_demux, int i_query, va_list args )
149 {
150 }
151
152 /*****************************************************************************
153  * Demux:
154  *****************************************************************************/
155 static int Demux( demux_t *p_demux )
156 {
157 }
158
159
160 /*****************************************************************************
161  * OpenDev: open the device and probe for capabilities
162  *****************************************************************************/
163 int OpenDev( demux_t *p_demux )
164 {
165     int i_device_index;
166
167     int i_fd;
168     demux_sys_t *p_sys = p_demux->p_sys;
169
170     if( ( i_fd = open( p_sys->psz_device, O_RDWR ) ) < 0 )
171     {
172         msg_Err( p_demux, "cannot open device (%s)", strerror( errno ) );
173         goto open_failed;
174     }
175
176     /* Get device capabilites */
177
178     if( ioctl( i_fd, VIDIOC_QUERYCAP, &p_sys->dev_cap ) < 0 )
179     {
180         msg_Err( p_demux, "cannot get capabilities (%s)", strerror( errno ) );
181         goto open_failed;
182     }
183
184   msg_Dbg( p_demux, "V4L2 device: %s using driver: %s (version: %u.%u.%u) on %s",
185                             p_sys->dev_cap.card,
186                             p_sys->dev_cap.driver,
187                             (p_sys->dev_cap.version >> 16) & 0xFF,
188                             (p_sys->dev_cap.version >> 8) & 0xFF,
189                             p_sys->dev_cap.version & 0xFF,
190                             p_sys->dev_cap.bus_info );
191
192     msg_Dbg( p_demux, "The device has the capabilities: (%c) Video Capure, "
193                                                        "(%c) Audio, "
194                                                        "(%c) Tuner",
195              ( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE  ? 'X':' '),
196              ( p_sys->dev_cap.capabilities & V4L2_CAP_AUDIO  ? 'X':' '),
197              ( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER  ? 'X':' ') );
198
199     msg_Dbg( p_demux, "Supported I/O methods are: (%c) Read/Write, "
200                                                  "(%c) Streaming, "
201                                                  "(%c) Asynchronous",
202             ( p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE ? 'X':' ' ),
203             ( p_sys->dev_cap.capabilities & V4L2_CAP_STREAMING ? 'X':' ' ),
204             ( p_sys->dev_cap.capabilities & V4L2_CAP_ASYNCIO ? 'X':' ' ) );
205
206     /* Now, enumerate all the video inputs. This is useless at the moment
207        since we have no way to present that info to the user except with
208        debug messages */
209
210     if( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE )
211     {
212         while( ioctl( i_fd, VIDIOC_S_INPUT, &p_sys->i_input ) >= 0 )
213         {
214             p_sys->i_input++;
215         }
216
217         p_sys->p_inputs = malloc( p_sys->i_input * sizeof( struct v4l2_input ) );
218         if( !p_sys->p_inputs ) goto open_failed;
219         memset( p_sys->p_inputs, 0, sizeof( struct v4l2_input ) );
220
221         for( i_device_index = 0; i_device_index < p_sys->i_input; i_device_index++ )
222         {
223             p_sys->p_inputs[i_device_index].index = i_device_index;
224
225             if( ioctl( i_fd, VIDIOC_ENUMINPUT, &p_sys->p_inputs[i_device_index] ) )
226             {
227                 msg_Err( p_demux, "cannot get video input characteristics (%s)",
228                                                  strerror( errno ) );
229                 goto open_failed;
230             }
231             msg_Dbg( p_demux, "Video input %i (%s) has type: %s",
232                                 i_device_index,
233                                 p_sys->p_inputs[i_device_index].name,
234                                 p_sys->p_inputs[i_device_index].type
235                                         == V4L2_INPUT_TYPE_TUNER ?
236                                         "Tuner adapter" :
237                                         "External analog input" );
238         }
239     }
240
241     /* initialize the structures for the ioctls */
242     for( i_device_index = 0; i_device_index < 32; i_device_index++ )
243     {
244         p_sys->p_audios[i_device_index].index = i_device_index;
245     }
246
247     /* Probe audio inputs */
248
249     if( p_sys->dev_cap.capabilities & V4L2_CAP_AUDIO )
250     {
251         while( p_sys->i_audio < 32 &&
252                ioctl( i_fd, VIDIOC_S_AUDIO, &p_sys->p_audios[p_sys->i_audio] ) >= 0 )
253         {
254             if( ioctl( i_fd, VIDIOC_G_AUDIO, &p_sys->p_audios[ p_sys->i_audio] ) < 0 )
255             {
256                 msg_Err( p_demux, "cannot get video input characteristics (%s)",
257                                                  strerror( errno ) );
258                 goto open_failed;
259             }
260
261             msg_Dbg( p_demux, "Audio device %i (%s) is %s",
262                                 p_sys->i_audio,
263                                 p_sys->p_audios[p_sys->i_audio].name,
264                                 p_sys->p_audios[p_sys->i_audio].capability &
265                                                     V4L2_AUDCAP_STEREO ?
266                                         "Stereo" : "Mono" );
267
268             p_sys->i_audio++;
269         }
270     }
271
272     if( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER )
273     {
274         struct v4l2_tuner tuner;
275         memset( &tuner, 0, sizeof( struct v4l2_tuner ) );
276
277         while( ioctl( i_fd, VIDIOC_S_TUNER, &tuner ) >= 0 )
278         {
279             p_sys->i_tuner++;
280             tuner.index = p_sys->i_tuner;
281         }
282
283         p_sys->p_tuners = malloc( p_sys->i_tuner * sizeof( struct v4l2_tuner ) );
284         if( !p_sys->p_tuners ) goto open_failed;
285         memset( p_sys->p_tuners, 0, sizeof( struct v4l2_tuner ) );
286
287         for( i_device_index = 0; i_device_index < p_sys->i_tuner; i_device_index++ )
288         {
289             p_sys->p_tuners[i_device_index].index = i_device_index;
290
291             if( ioctl( i_fd, VIDIOC_G_TUNER, &p_sys->p_tuners[i_device_index] ) )
292             {
293                 msg_Err( p_demux, "cannot get tuner characteristics (%s)",
294                                                  strerror( errno ) );
295                 goto open_failed;
296             }
297             msg_Dbg( p_demux, "Tuner %i (%s) has type: %s, "
298                               "frequency range: %.1f %s -> %.1f %s",
299                                 i_device_index,
300                                 p_sys->p_tuners[i_device_index].name,
301                                 p_sys->p_tuners[i_device_index].type
302                                         == V4L2_TUNER_RADIO ?
303                                         "Radio" : "Analog TV",
304                                 p_sys->p_tuners[i_device_index].rangelow * 62.5,
305                                 p_sys->p_tuners[i_device_index].capability &
306                                         V4L2_TUNER_CAP_LOW ?
307                                         "Hz" : "kHz",
308                                 p_sys->p_tuners[i_device_index].rangehigh * 62.5,
309                                 p_sys->p_tuners[i_device_index].capability &
310                                         V4L2_TUNER_CAP_LOW ?
311                                         "Hz" : "kHz" );
312         }
313     }
314
315     if( i_fd >= 0 ) close( i_fd );
316     return VLC_SUCCESS;
317
318 open_failed:
319     
320     if( i_fd >= 0 ) close( i_fd );
321     return VLC_EGENERIC;
322
323 }