1 /*****************************************************************************
2 * access.c : V4L2 compressed byte stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2011 the VideoLAN team
6 * Authors: Benjamin Pracht <bigben at videolan dot org>
7 * Richard Hosking <richard at hovis dot net>
8 * Antoine Cellerier <dionoea at videolan d.t org>
9 * Dennis Lou <dlou99 at yahoo dot com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_access.h>
50 struct buffer_t *bufv;
51 vlc_v4l2_ctrl_t *controls;
54 static block_t *AccessRead( access_t * );
55 static ssize_t AccessReadStream( access_t *, uint8_t *, size_t );
56 static int AccessControl( access_t *, int, va_list );
57 static int InitVideo(access_t *, int);
59 int AccessOpen( vlc_object_t *obj )
61 access_t *access = (access_t *)obj;
63 access_InitFields( access );
65 access_sys_t *sys = calloc (1, sizeof (*sys));
66 if( unlikely(sys == NULL) )
70 ParseMRL( obj, access->psz_location );
72 char *path = var_InheritString (obj, CFG_PREFIX"dev");
73 if (unlikely(path == NULL))
74 goto error; /* probably OOM */
75 msg_Dbg (obj, "opening device '%s'", path);
77 int rawfd = vlc_open (path, O_RDWR);
80 msg_Err (obj, "cannot open device '%s': %m", path);
86 int fd = v4l2_fd_open (rawfd, 0);
89 msg_Warn (obj, "cannot initialize user-space library: %m");
90 /* fallback to direct kernel mode anyway */
95 if (InitVideo (access, fd))
101 access->pf_seek = NULL;
102 access->pf_control = AccessControl;
109 int InitVideo (access_t *access, int fd)
111 access_sys_t *sys = access->p_sys;
113 /* Get device capabilites */
114 struct v4l2_capability cap;
115 if (v4l2_ioctl (fd, VIDIOC_QUERYCAP, &cap) < 0)
117 msg_Err (access, "cannot get device capabilities: %m");
121 msg_Dbg (access, "device %s using driver %s (version %u.%u.%u) on %s",
122 cap.card, cap.driver, (cap.version >> 16) & 0xFF,
123 (cap.version >> 8) & 0xFF, cap.version & 0xFF, cap.bus_info);
124 msg_Dbg (access, "the device has the capabilities: 0x%08X",
126 msg_Dbg (access, " (%c) Video Capture, (%c) Audio, (%c) Tuner, (%c) Radio",
127 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE ? 'X':' '),
128 (cap.capabilities & V4L2_CAP_AUDIO ? 'X':' '),
129 (cap.capabilities & V4L2_CAP_TUNER ? 'X':' '),
130 (cap.capabilities & V4L2_CAP_RADIO ? 'X':' '));
131 msg_Dbg (access, " (%c) Read/Write, (%c) Streaming, (%c) Asynchronous",
132 (cap.capabilities & V4L2_CAP_READWRITE ? 'X':' '),
133 (cap.capabilities & V4L2_CAP_STREAMING ? 'X':' '),
134 (cap.capabilities & V4L2_CAP_ASYNCIO ? 'X':' '));
136 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
138 msg_Err (access, "not a video capture device");
142 if (SetupInput (VLC_OBJECT(access), fd))
145 sys->controls = ControlsInit (VLC_OBJECT(access), fd);
147 /* Try and find default resolution if not specified */
148 struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
149 if (v4l2_ioctl (fd, VIDIOC_G_FMT, &fmt) < 0)
151 msg_Err (access, "cannot get default format: %m");
155 /* Print extra info */
156 msg_Dbg (access, "%d bytes maximum for complete image",
157 fmt.fmt.pix.sizeimage );
158 /* Check interlacing */
159 switch (fmt.fmt.pix.field)
161 case V4L2_FIELD_INTERLACED:
162 msg_Dbg (access, "Interlacing setting: interleaved");
164 sys->block_flags = BLOCK_FLAG_BOTTOM_FIELD_FIRST;
166 sys->block_flags = BLOCK_FLAG_TOP_FIELD_FIRST;
168 case V4L2_FIELD_INTERLACED_TB:
169 msg_Dbg (access, "Interlacing setting: interleaved top bottom" );
170 sys->block_flags = BLOCK_FLAG_TOP_FIELD_FIRST;
172 case V4L2_FIELD_INTERLACED_BT:
173 msg_Dbg (access, "Interlacing setting: interleaved bottom top" );
174 sys->block_flags = BLOCK_FLAG_BOTTOM_FIELD_FIRST;
180 /* Init I/O method */
181 if (cap.capabilities & V4L2_CAP_STREAMING)
184 sys->bufv = StartMmap (VLC_OBJECT(access), fd, &sys->bufc);
185 if (sys->bufv == NULL)
187 access->pf_block = AccessRead;
189 else if (cap.capabilities & V4L2_CAP_READWRITE)
191 sys->blocksize = fmt.fmt.pix.sizeimage;
193 access->pf_read = AccessReadStream;
197 msg_Err (access, "no supported I/O method");
203 void AccessClose( vlc_object_t *obj )
205 access_t *access = (access_t *)obj;
206 access_sys_t *sys = access->p_sys;
208 if (sys->bufv != NULL)
209 StopMmap (sys->fd, sys->bufv, sys->bufc);
210 ControlsDeinit( obj, sys->controls );
211 v4l2_close (sys->fd);
215 static block_t *AccessRead( access_t *access )
217 access_sys_t *sys = access->p_sys;
225 /* FIXME: kill timeout */
226 if( poll( &fd, 1, 500 ) <= 0 )
229 block_t *block = GrabVideo (VLC_OBJECT(access), sys->fd, sys->bufv);
232 block->i_pts = block->i_dts = mdate();
233 block->i_flags |= sys->block_flags;
238 static ssize_t AccessReadStream( access_t *access, uint8_t *buf, size_t len )
240 access_sys_t *sys = access->p_sys;
247 if( access->info.b_eof )
250 /* FIXME: kill timeout and vlc_object_alive() */
253 if( !vlc_object_alive(access) )
258 while( ( i_ret = poll( &ufd, 1, 500 ) ) == 0 );
263 msg_Err( access, "poll error: %m" );
267 i_ret = v4l2_read (sys->fd, buf, len);
269 access->info.b_eof = true;
271 access->info.i_pos += i_ret;
276 static int AccessControl( access_t *access, int query, va_list args )
281 case ACCESS_CAN_SEEK:
282 case ACCESS_CAN_FASTSEEK:
283 case ACCESS_CAN_PAUSE:
284 case ACCESS_CAN_CONTROL_PACE:
285 *va_arg( args, bool* ) = false;
289 case ACCESS_GET_PTS_DELAY:
290 *va_arg(args,int64_t *) = INT64_C(1000)
291 * var_InheritInteger( access, "live-caching" );
295 case ACCESS_SET_PAUSE_STATE:
299 case ACCESS_GET_TITLE_INFO:
300 case ACCESS_SET_TITLE:
301 case ACCESS_SET_SEEKPOINT:
302 case ACCESS_SET_PRIVATE_ID_STATE:
303 case ACCESS_GET_CONTENT_TYPE:
304 case ACCESS_GET_META:
308 msg_Warn( access, "Unimplemented query %d in control", query );