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 *****************************************************************************/
34 #include <sys/ioctl.h>
38 #include <vlc_common.h>
39 #include <vlc_demux.h>
44 static void *StreamThread (void *);
45 static void *ReadThread (void *);
46 static int DemuxControl( demux_t *, int, va_list );
47 static int InitVideo (demux_t *, int);
49 int DemuxOpen( vlc_object_t *obj )
51 demux_t *demux = (demux_t *)obj;
53 demux_sys_t *sys = calloc( 1, sizeof( demux_sys_t ) );
54 if( unlikely(sys == NULL) )
58 ParseMRL( obj, demux->psz_location );
60 char *path = var_InheritString (obj, CFG_PREFIX"dev");
61 if (unlikely(path == NULL))
62 goto error; /* probably OOM */
63 msg_Dbg (obj, "opening device '%s'", path);
65 int rawfd = vlc_open (path, O_RDWR);
68 msg_Err (obj, "cannot open device '%s': %m", path);
74 int fd = v4l2_fd_open (rawfd, 0);
77 msg_Warn (obj, "cannot initialize user-space library: %m");
78 /* fallback to direct kernel mode anyway */
82 if (InitVideo (demux, fd))
89 sys->controls = ControlsInit (VLC_OBJECT(demux), fd);
90 demux->pf_demux = NULL;
91 demux->pf_control = DemuxControl;
92 demux->info.i_update = 0;
93 demux->info.i_title = 0;
94 demux->info.i_seekpoint = 0;
110 /* NOTE: Currently vlc_v4l2_fmt_rank() assumes format are sorted in order of
111 * decreasing preference. */
112 static const vlc_v4l2_fmt_t v4l2_fmts[] =
114 /* Planar YUV 4:2:0 */
115 { V4L2_PIX_FMT_YUV420, VLC_CODEC_I420, 0, 0, 0 },
116 { V4L2_PIX_FMT_YVU420, VLC_CODEC_YV12, 0, 0, 0 },
117 { V4L2_PIX_FMT_YUV422P, VLC_CODEC_I422, 0, 0, 0 },
118 /* Packed YUV 4:2:2 */
119 { V4L2_PIX_FMT_YUYV, VLC_CODEC_YUYV, 0, 0, 0 },
120 { V4L2_PIX_FMT_UYVY, VLC_CODEC_UYVY, 0, 0, 0 },
121 { V4L2_PIX_FMT_YVYU, VLC_CODEC_YVYU, 0, 0, 0 },
122 { V4L2_PIX_FMT_VYUY, VLC_CODEC_VYUY, 0, 0, 0 },
124 { V4L2_PIX_FMT_YUV411P, VLC_CODEC_I411, 0, 0, 0 },
126 { V4L2_PIX_FMT_YUV410, VLC_CODEC_I410, 0, 0, 0 },
127 // { V4L2_PIX_FMT_YVU410 },
129 // { V4L2_PIX_FMT_NV24, },
130 // { V4L2_PIX_FMT_NV42, },
131 // { V4L2_PIX_FMT_NV16, VLC_CODEC_NV16, 0, 0, 0 },
132 // { V4L2_PIX_FMT_NV61, VLC_CODEC_NV61, 0, 0, 0 },
133 { V4L2_PIX_FMT_NV12, VLC_CODEC_NV12, 0, 0, 0 },
134 { V4L2_PIX_FMT_NV21, VLC_CODEC_NV21, 0, 0, 0 },
136 /* V4L2-documented but VLC-unsupported misc. YUV formats */
137 // { V4L2_PIX_FMT_Y41P },
138 // { V4L2_PIX_FMT_NV12MT, },
139 // { V4L2_PIX_FMT_M420, },
142 #ifdef WORDS_BIGENDIAN
143 { V4L2_PIX_FMT_RGB32, VLC_CODEC_RGB32, 0xFF00, 0xFF0000, 0xFF000000 },
144 { V4L2_PIX_FMT_BGR32, VLC_CODEC_RGB32, 0xFF000000, 0xFF0000, 0xFF00 },
145 { V4L2_PIX_FMT_RGB24, VLC_CODEC_RGB24, 0xFF0000, 0x00FF00, 0x0000FF },
146 { V4L2_PIX_FMT_BGR24, VLC_CODEC_RGB24, 0x0000FF, 0x00FF00, 0xFF0000 },
147 // { V4L2_PIX_FMT_BGR666, },
148 // { V4L2_PIX_FMT_RGB565, },
149 { V4L2_PIX_FMT_RGB565X, VLC_CODEC_RGB16, 0x001F, 0x07E0, 0xF800 },
150 // { V4L2_PIX_FMT_RGB555, },
151 { V4L2_PIX_FMT_RGB555X, VLC_CODEC_RGB15, 0x001F, 0x03E0, 0x7C00 },
152 // { V4L2_PIX_FMT_RGB444, VLC_CODEC_RGB12, 0x000F, 0xF000, 0x0F00 },
154 { V4L2_PIX_FMT_RGB32, VLC_CODEC_RGB32, 0x0000FF, 0x00FF00, 0xFF0000 },
155 { V4L2_PIX_FMT_BGR32, VLC_CODEC_RGB32, 0xFF0000, 0x00FF00, 0x0000FF },
156 { V4L2_PIX_FMT_RGB24, VLC_CODEC_RGB24, 0x0000FF, 0x00FF00, 0xFF0000 },
157 { V4L2_PIX_FMT_BGR24, VLC_CODEC_RGB24, 0xFF0000, 0x00FF00, 0x0000FF },
158 // { V4L2_PIX_FMT_BGR666, },
159 { V4L2_PIX_FMT_RGB565, VLC_CODEC_RGB16, 0x001F, 0x07E0, 0xF800 },
160 // { V4L2_PIX_FMT_RGB565X, },
161 { V4L2_PIX_FMT_RGB555, VLC_CODEC_RGB15, 0x001F, 0x03E0, 0x7C00 },
162 // { V4L2_PIX_FMT_RGB555X, },
163 // { V4L2_PIX_FMT_RGB444, VLC_CODEC_RGB12, 0x0F00, 0x00F0, 0x000F },
165 // { V4L2_PIX_FMT_RGB332, VLC_CODEC_RGB8, 0xC0, 0x38, 0x07 },
167 /* Bayer (sub-sampled RGB). Not supported. */
168 // { V4L2_PIX_FMT_SBGGR16, }
169 // { V4L2_PIX_FMT_SRGGB12, }
170 // { V4L2_PIX_FMT_SGRBG12, }
171 // { V4L2_PIX_FMT_SGBRG12, }
172 // { V4L2_PIX_FMT_SBGGR12, }
173 // { V4L2_PIX_FMT_SRGGB10, }
174 // { V4L2_PIX_FMT_SGRBG10, }
175 // { V4L2_PIX_FMT_SGBRG10, }
176 // { V4L2_PIX_FMT_SBGGR10, }
177 // { V4L2_PIX_FMT_SBGGR8, }
178 // { V4L2_PIX_FMT_SGBRG8, }
179 // { V4L2_PIX_FMT_SGRBG8, }
180 // { V4L2_PIX_FMT_SRGGB8, }
182 /* Compressed data types */
183 { V4L2_PIX_FMT_JPEG, VLC_CODEC_MJPG, 0, 0, 0 },
184 #ifdef V4L2_PIX_FMT_H264
185 { V4L2_PIX_FMT_H264, VLC_CODEC_H264, 0, 0, 0 },
186 /* FIXME: fill p_extra for avc1... */
187 // { V4L2_PIX_FMT_H264_NO_SC, VLC_FOURCC('a','v','c','1'), 0, 0, 0 }
188 { V4L2_PIX_FMT_MPEG4, VLC_CODEC_MP4V, 0, 0, 0 },
189 { V4L2_PIX_FMT_XVID, VLC_CODEC_MP4V, 0, 0, 0 },
190 { V4L2_PIX_FMT_H263, VLC_CODEC_H263, 0, 0, 0 },
191 { V4L2_PIX_FMT_MPEG2, VLC_CODEC_MPGV, 0, 0, 0 },
192 { V4L2_PIX_FMT_MPEG1, VLC_CODEC_MPGV, 0, 0, 0 },
193 { V4L2_PIX_FMT_VC1_ANNEX_G, VLC_CODEC_VC1, 0, 0, 0 },
194 { V4L2_PIX_FMT_VC1_ANNEX_L, VLC_CODEC_VC1, 0, 0, 0 },
196 //V4L2_PIX_FMT_MPEG -> use access
198 /* Reserved formats */
199 { V4L2_PIX_FMT_MJPEG, VLC_CODEC_MJPG, 0, 0, 0 },
200 //V4L2_PIX_FMT_DV -> use access
203 // { V4L2_PIX_FMT_Y16, },
204 // { V4L2_PIX_FMT_Y12, },
205 // { V4L2_PIX_FMT_Y10, },
206 // { V4L2_PIX_FMT_Y10BPACK, },
207 { V4L2_PIX_FMT_GREY, VLC_CODEC_GREY, 0, 0, 0 },
210 static const vlc_v4l2_fmt_t *vlc_from_v4l2_fourcc (uint32_t fourcc)
212 for (size_t i = 0; i < sizeof (v4l2_fmts) / sizeof (v4l2_fmts[0]); i++)
213 if (v4l2_fmts[i].v4l2 == fourcc)
214 return v4l2_fmts + i;
218 static size_t vlc_v4l2_fmt_rank (const vlc_v4l2_fmt_t *fmt)
223 ptrdiff_t d = fmt - v4l2_fmts;
225 assert (d < (ptrdiff_t)(sizeof (v4l2_fmts) / sizeof (v4l2_fmts[0])));
229 static vlc_fourcc_t var_InheritFourCC (vlc_object_t *obj, const char *varname)
231 char *str = var_InheritString (obj, varname);
235 vlc_fourcc_t fourcc = vlc_fourcc_GetCodecFromString (VIDEO_ES, str);
237 msg_Err (obj, "invalid codec %s", str);
241 #define var_InheritFourCC(o, v) var_InheritFourCC(VLC_OBJECT(o), v)
243 static void GetAR (int fd, unsigned *restrict num, unsigned *restrict den)
245 struct v4l2_cropcap cropcap = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
247 /* TODO: get CROPCAP only once (see ResetCrop()). */
248 if (v4l2_ioctl (fd, VIDIOC_CROPCAP, &cropcap) < 0)
253 *num = cropcap.pixelaspect.numerator;
254 *den = cropcap.pixelaspect.denominator;
257 static int InitVideo (demux_t *demux, int fd)
259 demux_sys_t *sys = demux->p_sys;
261 /* Get device capabilites */
262 struct v4l2_capability cap;
263 if (v4l2_ioctl (fd, VIDIOC_QUERYCAP, &cap) < 0)
265 msg_Err (demux, "cannot get device capabilities: %m");
269 msg_Dbg (demux, "device %s using driver %s (version %u.%u.%u) on %s",
270 cap.card, cap.driver, (cap.version >> 16) & 0xFF,
271 (cap.version >> 8) & 0xFF, cap.version & 0xFF, cap.bus_info);
274 #ifdef V4L2_CAP_DEVICE_CAPS
275 if (cap.capabilities & V4L2_CAP_DEVICE_CAPS)
277 msg_Dbg (demux, " with capabilities 0x%08"PRIX32" "
278 "(overall 0x%08"PRIX32")", cap.device_caps, cap.capabilities);
279 caps = cap.device_caps;
284 msg_Dbg (demux, " with unknown capabilities "
285 "(overall 0x%08"PRIX32")", cap.capabilities);
286 caps = cap.capabilities;
288 if (!(caps & V4L2_CAP_VIDEO_CAPTURE))
290 msg_Err (demux, "not a video capture device");
294 if (SetupInput (VLC_OBJECT(demux), fd))
297 /* Picture format negotiation */
298 const vlc_v4l2_fmt_t *selected = NULL;
299 vlc_fourcc_t reqfourcc = var_InheritFourCC (demux, CFG_PREFIX"chroma");
302 for (struct v4l2_fmtdesc codec = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
303 v4l2_ioctl (fd, VIDIOC_ENUM_FMT, &codec) >= 0;
305 { /* Enumerate available chromas */
306 const vlc_v4l2_fmt_t *dsc = vlc_from_v4l2_fourcc (codec.pixelformat);
308 msg_Dbg (demux, " %s %s format %4.4s (%4.4s): %s",
309 (codec.flags & V4L2_FMT_FLAG_EMULATED) ? "emulates" : "supports",
310 (codec.flags & V4L2_FMT_FLAG_COMPRESSED) ? "compressed" : "raw",
311 (char *)&codec.pixelformat,
312 (dsc != NULL) ? (const char *)&dsc->vlc : "N.A.",
316 continue; /* ignore VLC-unsupported codec */
318 if (dsc->vlc == reqfourcc)
320 msg_Dbg (demux, " matches the requested format");
322 break; /* always select the requested format if found */
325 if (codec.flags & V4L2_FMT_FLAG_EMULATED)
328 continue; /* ignore emulated format if possible */
333 if (vlc_v4l2_fmt_rank (dsc) > vlc_v4l2_fmt_rank (selected))
334 continue; /* ignore if rank is worse */
339 if (selected == NULL)
341 msg_Err (demux, "cannot negotiate supported video format");
344 msg_Dbg (demux, "selected format %4.4s (%4.4s)",
345 (const char *)&selected->v4l2, (const char *)&selected->vlc);
347 /* Find best resolution and frame rate available */
348 struct v4l2_format fmt;
349 struct v4l2_streamparm parm;
350 if (SetupFormat (demux, fd, selected->v4l2, &fmt, &parm))
354 uint32_t width = var_InheritInteger (demux, CFG_PREFIX"width");
355 if (width != (uint32_t)-1)
356 fmt.fmt.pix.width = width; /* override width */
357 uint32_t height = var_InheritInteger (demux, CFG_PREFIX"height");
358 if (height != (uint32_t)-1)
359 fmt.fmt.pix.height = height; /* override height */
362 /* Print extra info */
363 msg_Dbg (demux, "%d bytes maximum for complete image",
364 fmt.fmt.pix.sizeimage);
365 /* Check interlacing */
366 switch (fmt.fmt.pix.field)
368 case V4L2_FIELD_NONE:
369 msg_Dbg (demux, "Interlacing setting: progressive");
372 msg_Dbg (demux, "Interlacing setting: top field only");
374 case V4L2_FIELD_BOTTOM:
375 msg_Dbg (demux, "Interlacing setting: bottom field only");
377 case V4L2_FIELD_INTERLACED:
378 msg_Dbg (demux, "Interlacing setting: interleaved");
380 sys->i_block_flags = BLOCK_FLAG_BOTTOM_FIELD_FIRST;
382 sys->i_block_flags = BLOCK_FLAG_TOP_FIELD_FIRST;
384 case V4L2_FIELD_SEQ_TB:
385 msg_Dbg (demux, "Interlacing setting: sequential top bottom (TODO)");
387 case V4L2_FIELD_SEQ_BT:
388 msg_Dbg (demux, "Interlacing setting: sequential bottom top (TODO)");
390 case V4L2_FIELD_ALTERNATE:
391 msg_Dbg (demux, "Interlacing setting: alternate fields (TODO)");
392 fmt.fmt.pix.height *= 2;
394 case V4L2_FIELD_INTERLACED_TB:
395 msg_Dbg (demux, "Interlacing setting: interleaved top bottom");
396 sys->i_block_flags = BLOCK_FLAG_TOP_FIELD_FIRST;
398 case V4L2_FIELD_INTERLACED_BT:
399 msg_Dbg (demux, "Interlacing setting: interleaved bottom top");
400 sys->i_block_flags = BLOCK_FLAG_BOTTOM_FIELD_FIRST;
403 msg_Warn (demux, "Interlacing setting: unknown type (%d)",
408 /* Declare our unique elementary (video) stream */
411 es_format_Init (&es_fmt, VIDEO_ES, selected->vlc);
412 es_fmt.video.i_rmask = selected->red;
413 es_fmt.video.i_gmask = selected->green;
414 es_fmt.video.i_bmask = selected->blue;
415 es_fmt.video.i_width = fmt.fmt.pix.width;
416 es_fmt.video.i_height = fmt.fmt.pix.height;
417 es_fmt.video.i_frame_rate = parm.parm.capture.timeperframe.denominator;
418 es_fmt.video.i_frame_rate_base = parm.parm.capture.timeperframe.numerator;
419 GetAR (fd, &es_fmt.video.i_sar_num, &es_fmt.video.i_sar_den);
421 msg_Dbg (demux, "added new video ES %4.4s %ux%u", (char *)&es_fmt.i_codec,
422 es_fmt.video.i_width, es_fmt.video.i_height);
423 msg_Dbg (demux, " frame rate: %u/%u", es_fmt.video.i_frame_rate,
424 es_fmt.video.i_frame_rate_base);
425 msg_Dbg (demux, " aspect ratio: %u/%u", es_fmt.video.i_sar_num,
426 es_fmt.video.i_sar_den);
427 sys->p_es = es_out_Add (demux->out, &es_fmt);
429 /* Init I/O method */
430 void *(*entry) (void *);
431 if (caps & V4L2_CAP_STREAMING)
433 sys->bufv = InitMmap (VLC_OBJECT(demux), fd, &sys->bufc);
434 if (sys->bufv == NULL)
436 for (uint32_t i = 0; i < sys->bufc; i++)
438 struct v4l2_buffer buf = {
439 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
440 .memory = V4L2_MEMORY_MMAP,
444 if (v4l2_ioctl (fd, VIDIOC_QBUF, &buf) < 0)
446 msg_Err (demux, "cannot queue buffer: %m");
451 enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
452 if (v4l2_ioctl (fd, VIDIOC_STREAMON, &buf_type) < 0)
454 msg_Err (demux, "cannot start streaming: %m");
458 sys->io = IO_METHOD_MMAP;
459 entry = StreamThread;
461 else if (caps & V4L2_CAP_READWRITE)
463 sys->blocksize = fmt.fmt.pix.sizeimage;
464 sys->io = IO_METHOD_READ;
469 msg_Err (demux, "no supported I/O method");
473 if (vlc_clone (&sys->thread, entry, demux, VLC_THREAD_PRIORITY_INPUT))
478 void DemuxClose( vlc_object_t *obj )
480 demux_t *demux = (demux_t *)obj;
481 demux_sys_t *sys = demux->p_sys;
484 vlc_cancel (sys->thread);
485 vlc_join (sys->thread, NULL);
487 /* Stop video capture */
496 /* NOTE: Some buggy drivers hang if buffers are not unmapped before
498 for (uint32_t i = 0; i < sys->bufc; i++)
500 struct v4l2_buffer buf = {
501 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
502 .memory = V4L2_MEMORY_MMAP,
504 v4l2_ioctl (fd, VIDIOC_DQBUF, &buf);
505 v4l2_munmap (sys->bufv[i].start, sys->bufv[i].length);
507 enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
508 v4l2_ioctl( sys->i_fd, VIDIOC_STREAMOFF, &buf_type );
514 ControlsDeinit( obj, sys->controls );
519 static void *StreamThread (void *data)
521 demux_t *demux = data;
522 demux_sys_t *sys = demux->p_sys;
524 struct pollfd ufd[1];
527 ufd[0].events = POLLIN | POLLPRI;
532 if (poll (ufd, 1, -1) == -1)
535 msg_Err (demux, "poll error: %m");
539 int canc = vlc_savecancel ();
540 block_t *block = GrabVideo (VLC_OBJECT(demux), fd, sys->bufv);
543 block->i_pts = block->i_dts = mdate ();
544 block->i_flags |= sys->i_block_flags;
545 es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts);
546 es_out_Send (demux->out, sys->p_es, block);
548 vlc_restorecancel (canc);
554 static void *ReadThread (void *data)
556 demux_t *demux = data;
557 demux_sys_t *sys = demux->p_sys;
559 struct pollfd ufd[1];
562 ufd[0].events = POLLIN | POLLPRI;
567 if (poll (ufd, 1, -1) == -1)
570 msg_Err (demux, "poll error: %m");
574 block_t *block = block_Alloc (sys->blocksize);
575 if (unlikely(block == NULL))
577 msg_Err (demux, "read error: %m");
578 v4l2_read (fd, NULL, 0); /* discard frame */
581 block->i_pts = block->i_dts = mdate ();
582 block->i_flags |= sys->i_block_flags;
584 int canc = vlc_savecancel ();
585 ssize_t val = v4l2_read (fd, block->p_buffer, block->i_buffer);
588 block->i_buffer = val;
589 es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts);
590 es_out_Send (demux->out, sys->p_es, block);
593 block_Release (block);
594 vlc_restorecancel (canc);
599 static int DemuxControl( demux_t *demux, int query, va_list args )
603 /* Special for access_demux */
604 case DEMUX_CAN_PAUSE:
606 case DEMUX_CAN_CONTROL_PACE:
607 *va_arg( args, bool * ) = false;
610 case DEMUX_GET_PTS_DELAY:
611 *va_arg(args,int64_t *) = INT64_C(1000)
612 * var_InheritInteger( demux, "live-caching" );
616 *va_arg( args, int64_t * ) = mdate();
619 /* TODO implement others */