1 /*****************************************************************************
2 * demux.c : V4L2 raw video demux 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 *****************************************************************************/
33 #include <sys/ioctl.h>
37 #include <vlc_demux.h>
40 static int DemuxControl( demux_t *, int, va_list );
41 static int Demux( demux_t * );
43 int DemuxOpen( vlc_object_t *obj )
45 demux_t *demux = (demux_t *)obj;
47 demux_sys_t *sys = calloc( 1, sizeof( demux_sys_t ) );
48 if( unlikely(sys == NULL) )
52 ParseMRL( obj, demux->psz_location );
54 char *path = var_InheritString (obj, CFG_PREFIX"dev");
55 if (unlikely(path == NULL))
56 goto error; /* probably OOM */
57 msg_Dbg (obj, "opening device '%s'", path);
59 int rawfd = vlc_open (path, O_RDWR);
62 msg_Err (obj, "cannot open device '%s': %m", path);
68 int fd = v4l2_fd_open (rawfd, 0);
71 msg_Warn (obj, "cannot initialize user-space library: %m");
72 /* fallback to direct kernel mode anyway */
76 if (InitVideo (obj, fd, sys, true))
83 demux->pf_demux = Demux;
84 demux->pf_control = DemuxControl;
85 demux->info.i_update = 0;
86 demux->info.i_title = 0;
87 demux->info.i_seekpoint = 0;
94 void DemuxClose( vlc_object_t *obj )
96 demux_t *demux = (demux_t *)obj;
97 demux_sys_t *sys = demux->p_sys;
100 /* Stop video capture */
108 case IO_METHOD_USERPTR:
110 /* NOTE: Some buggy drivers hang if buffers are not unmapped before
112 for( unsigned i = 0; i < sys->i_nbuffers; i++ )
114 struct v4l2_buffer buf = {
115 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
116 .memory = ( sys->io == IO_METHOD_USERPTR ) ?
117 V4L2_MEMORY_USERPTR : V4L2_MEMORY_MMAP,
119 v4l2_ioctl( fd, VIDIOC_DQBUF, &buf );
121 enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
122 v4l2_ioctl( sys->i_fd, VIDIOC_STREAMOFF, &buf_type );
127 /* Free Video Buffers */
128 if( sys->p_buffers ) {
132 free( sys->p_buffers[0].start );
136 for( unsigned i = 0; i < sys->i_nbuffers; ++i )
137 v4l2_munmap( sys->p_buffers[i].start,
138 sys->p_buffers[i].length );
141 case IO_METHOD_USERPTR:
142 for( unsigned i = 0; i < sys->i_nbuffers; ++i )
143 free( sys->p_buffers[i].start );
146 free( sys->p_buffers );
149 ControlsDeinit( obj, sys->controls );
154 static int DemuxControl( demux_t *demux, int query, va_list args )
158 /* Special for access_demux */
159 case DEMUX_CAN_PAUSE:
161 case DEMUX_CAN_CONTROL_PACE:
162 *va_arg( args, bool * ) = false;
165 case DEMUX_GET_PTS_DELAY:
166 *va_arg(args,int64_t *) = INT64_C(1000)
167 * var_InheritInteger( demux, "live-caching" );
171 *va_arg( args, int64_t * ) = mdate();
174 /* TODO implement others */
182 /** Gets a frame in read/write mode */
183 static block_t *BlockRead( vlc_object_t *obj, int fd, size_t size )
185 block_t *block = block_Alloc( size );
186 if( unlikely(block == NULL) )
189 ssize_t val = v4l2_read( fd, block->p_buffer, size );
192 block_Release( block );
197 case EIO: /* could be ignored per specification */
200 msg_Err( obj, "cannot read frame: %m" );
204 block->i_buffer = val;
208 static int Demux( demux_t *demux )
210 demux_sys_t *sys = demux->p_sys;
214 ufd.events = POLLIN|POLLPRI;
216 /* FIXME: remove timeout */
217 while( poll( &ufd, 1, 500 ) == -1 )
220 msg_Err( demux, "poll error: %m" );
224 if( ufd.revents == 0 )
229 if( sys->io == IO_METHOD_READ )
230 block = BlockRead( VLC_OBJECT(demux), ufd.fd, sys->blocksize );
232 block = GrabVideo( VLC_OBJECT(demux), sys );
236 block->i_pts = block->i_dts = mdate();
237 block->i_flags |= sys->i_block_flags;
238 es_out_Control( demux->out, ES_OUT_SET_PCR, block->i_pts );
239 es_out_Send( demux->out, sys->p_es, block );
243 static float GetMaxFPS( vlc_object_t *obj, int fd, uint32_t pixel_format,
244 uint32_t width, uint32_t height )
246 #ifdef VIDIOC_ENUM_FRAMEINTERVALS
247 /* This is new in Linux 2.6.19 */
248 struct v4l2_frmivalenum fie = {
249 .pixel_format = pixel_format,
254 if( v4l2_ioctl( fd, VIDIOC_ENUM_FRAMEINTERVALS, &fie ) < 0 )
259 case V4L2_FRMIVAL_TYPE_DISCRETE:
264 float fps = (float)fie.discrete.denominator
265 / (float)fie.discrete.numerator;
268 msg_Dbg( obj, " discrete frame interval %"PRIu32"/%"PRIu32
270 fie.discrete.numerator, fie.discrete.denominator );
272 } while( v4l2_ioctl( fd, VIDIOC_ENUM_FRAMEINTERVALS, &fie ) >= 0 );
276 case V4L2_FRMIVAL_TYPE_STEPWISE:
277 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
278 msg_Dbg( obj, " frame intervals from %"PRIu32"/%"PRIu32
279 "to %"PRIu32"/%"PRIu32" supported",
280 fie.stepwise.min.numerator, fie.stepwise.min.denominator,
281 fie.stepwise.max.numerator, fie.stepwise.max.denominator );
282 if( fie.type == V4L2_FRMIVAL_TYPE_STEPWISE )
283 msg_Dbg( obj, " with %"PRIu32"/%"PRIu32" step",
284 fie.stepwise.step.numerator,
285 fie.stepwise.step.denominator );
286 return __MAX( (float)fie.stepwise.max.denominator
287 / (float)fie.stepwise.max.numerator,
288 (float)fie.stepwise.min.denominator
289 / (float)fie.stepwise.min.numerator );
295 float GetAbsoluteMaxFrameRate( vlc_object_t *obj, int fd,
296 uint32_t pixel_format )
298 #ifdef VIDIOC_ENUM_FRAMESIZES
299 /* This is new in Linux 2.6.19 */
300 struct v4l2_frmsizeenum fse = {
301 .pixel_format = pixel_format
304 if( v4l2_ioctl( fd, VIDIOC_ENUM_FRAMESIZES, &fse ) < 0 )
310 case V4L2_FRMSIZE_TYPE_DISCRETE:
313 float fps = GetMaxFPS( obj, fd, pixel_format,
314 fse.discrete.width, fse.discrete.height );
318 } while( v4l2_ioctl( fd, VIDIOC_ENUM_FRAMESIZES, &fse ) >= 0 );
321 case V4L2_FRMSIZE_TYPE_STEPWISE:
322 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
323 msg_Dbg( obj, " sizes from %"PRIu32"x%"PRIu32" "
324 "to %"PRIu32"x%"PRIu32" supported",
325 fse.stepwise.min_width, fse.stepwise.min_height,
326 fse.stepwise.max_width, fse.stepwise.max_height );
327 if( fse.type == V4L2_FRMSIZE_TYPE_STEPWISE )
328 msg_Dbg( obj, " with %"PRIu32"x%"PRIu32" steps",
329 fse.stepwise.step_width, fse.stepwise.step_height );
331 for( uint32_t width = fse.stepwise.min_width;
332 width <= fse.stepwise.max_width;
333 width += fse.stepwise.step_width )
334 for( uint32_t height = fse.stepwise.min_height;
335 height <= fse.stepwise.max_width;
336 height += fse.stepwise.step_height )
338 float fps = GetMaxFPS( obj, fd, pixel_format, width, height );
350 void GetMaxDimensions( vlc_object_t *obj, int fd, uint32_t pixel_format,
351 float fps_min, uint32_t *pwidth, uint32_t *pheight )
356 #ifdef VIDIOC_ENUM_FRAMESIZES
357 /* This is new in Linux 2.6.19 */
358 struct v4l2_frmsizeenum fse = {
359 .pixel_format = pixel_format
362 if( v4l2_ioctl( fd, VIDIOC_ENUM_FRAMESIZES, &fse ) < 0 )
367 case V4L2_FRMSIZE_TYPE_DISCRETE:
370 msg_Dbg( obj, " discrete size %"PRIu32"x%"PRIu32" supported",
371 fse.discrete.width, fse.discrete.height );
373 float fps = GetMaxFPS( obj, fd, pixel_format,
374 fse.discrete.width, fse.discrete.height );
375 if( fps >= fps_min && fse.discrete.width > *pwidth )
377 *pwidth = fse.discrete.width;
378 *pheight = fse.discrete.height;
382 while( v4l2_ioctl( fd, VIDIOC_ENUM_FRAMESIZES, &fse ) >= 0 );
385 case V4L2_FRMSIZE_TYPE_STEPWISE:
386 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
387 msg_Dbg( obj, " sizes from %"PRIu32"x%"PRIu32" "
388 "to %"PRIu32"x%"PRIu32" supported",
389 fse.stepwise.min_width, fse.stepwise.min_height,
390 fse.stepwise.max_width, fse.stepwise.max_height );
391 if( fse.type == V4L2_FRMSIZE_TYPE_STEPWISE )
392 msg_Dbg( obj, " with %"PRIu32"x%"PRIu32" steps",
393 fse.stepwise.step_width, fse.stepwise.step_height );
395 for( uint32_t width = fse.stepwise.min_width;
396 width <= fse.stepwise.max_width;
397 width += fse.stepwise.step_width )
398 for( uint32_t height = fse.stepwise.min_height;
399 height <= fse.stepwise.max_width;
400 height += fse.stepwise.step_height )
402 float fps = GetMaxFPS( obj, fd, pixel_format, width, height );
403 if( fps >= fps_min && width > *pwidth )