]> git.sesse.net Git - vlc/blob - modules/access/v4l2/demux.c
v4l2: GrabVideo() cleanup
[vlc] / modules / access / v4l2 / demux.c
1 /*****************************************************************************
2  * demux.c : V4L2 raw video demux module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002-2011 the VideoLAN team
5  *
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>
10  *
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.
15  *
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.
20  *
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  *****************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <math.h>
31 #include <errno.h>
32 #include <assert.h>
33 #include <fcntl.h>
34 #include <sys/ioctl.h>
35 #include <sys/mman.h>
36 #include <poll.h>
37
38 #include <vlc_common.h>
39 #include <vlc_demux.h>
40 #include <vlc_fs.h>
41
42 #include "v4l2.h"
43
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);
48
49 int DemuxOpen( vlc_object_t *obj )
50 {
51     demux_t *demux = (demux_t *)obj;
52
53     demux_sys_t *sys = calloc( 1, sizeof( demux_sys_t ) );
54     if( unlikely(sys == NULL) )
55         return VLC_ENOMEM;
56     demux->p_sys = sys;
57
58     ParseMRL( obj, demux->psz_location );
59
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);
64
65     int rawfd = vlc_open (path, O_RDWR);
66     if (rawfd == -1)
67     {
68         msg_Err (obj, "cannot open device '%s': %m", path);
69         free (path);
70         goto error;
71     }
72     free (path);
73
74     int fd = v4l2_fd_open (rawfd, 0);
75     if (fd == -1)
76     {
77         msg_Warn (obj, "cannot initialize user-space library: %m");
78         /* fallback to direct kernel mode anyway */
79         fd = rawfd;
80     }
81
82     if (InitVideo (demux, fd))
83     {
84         v4l2_close (fd);
85         goto error;
86     }
87
88     sys->i_fd = 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;
95     return VLC_SUCCESS;
96 error:
97     free (sys);
98     return VLC_EGENERIC;
99 }
100
101 typedef struct
102 {
103     uint32_t v4l2;
104     vlc_fourcc_t vlc;
105     uint32_t red;
106     uint32_t green;
107     uint32_t blue;
108 } vlc_v4l2_fmt_t;
109
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[] =
113 {
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 },
123
124     { V4L2_PIX_FMT_YUV411P,  VLC_CODEC_I411, 0, 0, 0 },
125
126     { V4L2_PIX_FMT_YUV410,   VLC_CODEC_I410, 0, 0, 0 },
127 //  { V4L2_PIX_FMT_YVU410     },
128
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 },
135
136     /* V4L2-documented but VLC-unsupported misc. YUV formats */
137 //  { V4L2_PIX_FMT_Y41P       },
138 //  { V4L2_PIX_FMT_NV12MT,    },
139 //  { V4L2_PIX_FMT_M420,      },
140
141     /* Packed RGB */
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 },
153 #else
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 },
164 #endif
165 //  { V4L2_PIX_FMT_RGB332,   VLC_CODEC_RGB8,        0xC0,     0x38,     0x07 },
166
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,   }
181
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 },
195 #endif
196     //V4L2_PIX_FMT_MPEG -> use access
197
198     /* Reserved formats */
199     { V4L2_PIX_FMT_MJPEG,   VLC_CODEC_MJPG, 0, 0, 0 },
200     //V4L2_PIX_FMT_DV -> use access
201
202     /* Grey scale */
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 },
208 };
209
210 static const vlc_v4l2_fmt_t *vlc_from_v4l2_fourcc (uint32_t fourcc)
211 {
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;
215      return NULL;
216 }
217
218 static size_t vlc_v4l2_fmt_rank (const vlc_v4l2_fmt_t *fmt)
219 {
220     if (fmt == NULL)
221         return SIZE_MAX;
222
223     ptrdiff_t d = fmt - v4l2_fmts;
224     assert (d >= 0);
225     assert (d < (ptrdiff_t)(sizeof (v4l2_fmts) / sizeof (v4l2_fmts[0])));
226     return d;
227 }
228
229 static vlc_fourcc_t var_InheritFourCC (vlc_object_t *obj, const char *varname)
230 {
231     char *str = var_InheritString (obj, varname);
232     if (str == NULL)
233         return 0;
234
235     vlc_fourcc_t fourcc = vlc_fourcc_GetCodecFromString (VIDEO_ES, str);
236     if (fourcc == 0)
237         msg_Err (obj, "invalid codec %s", str);
238     free (str);
239     return fourcc;
240 }
241 #define var_InheritFourCC(o, v) var_InheritFourCC(VLC_OBJECT(o), v)
242
243 static void GetAR (int fd, unsigned *restrict num, unsigned *restrict den)
244 {
245     struct v4l2_cropcap cropcap = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
246
247     /* TODO: get CROPCAP only once (see ResetCrop()). */
248     if (v4l2_ioctl (fd, VIDIOC_CROPCAP, &cropcap) < 0)
249     {
250         *num = *den = 1;
251         return;
252     }
253     *num = cropcap.pixelaspect.numerator;
254     *den = cropcap.pixelaspect.denominator;
255 }
256
257 static int InitVideo (demux_t *demux, int fd)
258 {
259     demux_sys_t *sys = demux->p_sys;
260
261     /* Get device capabilites */
262     struct v4l2_capability cap;
263     if (v4l2_ioctl (fd, VIDIOC_QUERYCAP, &cap) < 0)
264     {
265         msg_Err (demux, "cannot get device capabilities: %m");
266         return -1;
267     }
268
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);
272
273     uint32_t caps;
274 #ifdef V4L2_CAP_DEVICE_CAPS
275     if (cap.capabilities & V4L2_CAP_DEVICE_CAPS)
276     {
277         msg_Dbg (demux, " with capabilities 0x%08"PRIX32" "
278                  "(overall 0x%08"PRIX32")", cap.device_caps, cap.capabilities);
279         caps = cap.device_caps;
280     }
281     else
282 #endif
283     {
284         msg_Dbg (demux, " with unknown capabilities  "
285                  "(overall 0x%08"PRIX32")", cap.capabilities);
286         caps = cap.capabilities;
287     }
288     if (!(caps & V4L2_CAP_VIDEO_CAPTURE))
289     {
290         msg_Err (demux, "not a video capture device");
291         return -1;
292     }
293
294     if (SetupInput (VLC_OBJECT(demux), fd))
295         return -1;
296
297     /* Picture format negotiation */
298     const vlc_v4l2_fmt_t *selected = NULL;
299     vlc_fourcc_t reqfourcc = var_InheritFourCC (demux, CFG_PREFIX"chroma");
300     bool native = false;
301
302     for (struct v4l2_fmtdesc codec = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
303          v4l2_ioctl (fd, VIDIOC_ENUM_FMT, &codec) >= 0;
304          codec.index++)
305     {   /* Enumerate available chromas */
306         const vlc_v4l2_fmt_t *dsc = vlc_from_v4l2_fourcc (codec.pixelformat);
307
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.",
313                  codec.description);
314
315         if (dsc == NULL)
316             continue; /* ignore VLC-unsupported codec */
317
318         if (dsc->vlc == reqfourcc)
319         {
320             msg_Dbg (demux, "  matches the requested format");
321             selected = dsc;
322             break; /* always select the requested format if found */
323         }
324
325         if (codec.flags & V4L2_FMT_FLAG_EMULATED)
326         {
327             if (native)
328                 continue; /* ignore emulated format if possible */
329         }
330         else
331             native = true;
332
333         if (vlc_v4l2_fmt_rank (dsc) > vlc_v4l2_fmt_rank (selected))
334             continue; /* ignore if rank is worse */
335
336         selected = dsc;
337     }
338
339     if (selected == NULL)
340     {
341         msg_Err (demux, "cannot negotiate supported video format");
342         return -1;
343     }
344     msg_Dbg (demux, "selected format %4.4s (%4.4s)",
345              (const char *)&selected->v4l2, (const char *)&selected->vlc);
346
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))
351         return -1;
352
353 #if 0
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 */
360 #endif
361
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)
367     {
368         case V4L2_FIELD_NONE:
369             msg_Dbg (demux, "Interlacing setting: progressive");
370             break;
371         case V4L2_FIELD_TOP:
372             msg_Dbg (demux, "Interlacing setting: top field only");
373             break;
374         case V4L2_FIELD_BOTTOM:
375             msg_Dbg (demux, "Interlacing setting: bottom field only");
376             break;
377         case V4L2_FIELD_INTERLACED:
378             msg_Dbg (demux, "Interlacing setting: interleaved");
379             /*if (NTSC)
380                 sys->i_block_flags = BLOCK_FLAG_BOTTOM_FIELD_FIRST;
381             else*/
382                 sys->i_block_flags = BLOCK_FLAG_TOP_FIELD_FIRST;
383             break;
384         case V4L2_FIELD_SEQ_TB:
385             msg_Dbg (demux, "Interlacing setting: sequential top bottom (TODO)");
386             break;
387         case V4L2_FIELD_SEQ_BT:
388             msg_Dbg (demux, "Interlacing setting: sequential bottom top (TODO)");
389             break;
390         case V4L2_FIELD_ALTERNATE:
391             msg_Dbg (demux, "Interlacing setting: alternate fields (TODO)");
392             fmt.fmt.pix.height *= 2;
393             break;
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;
397             break;
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;
401             break;
402         default:
403             msg_Warn (demux, "Interlacing setting: unknown type (%d)",
404                       fmt.fmt.pix.field);
405             break;
406     }
407
408     /* Declare our unique elementary (video) stream */
409     es_format_t es_fmt;
410
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);
420
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);
428
429     /* Init I/O method */
430     void *(*entry) (void *);
431     if (caps & V4L2_CAP_STREAMING)
432     {
433         sys->bufv = InitMmap (VLC_OBJECT(demux), fd, &sys->bufc);
434         if (sys->bufv == NULL)
435             return -1;
436         for (uint32_t i = 0; i < sys->bufc; i++)
437         {
438             struct v4l2_buffer buf = {
439                 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
440                 .memory = V4L2_MEMORY_MMAP,
441                 .index = i,
442             };
443
444             if (v4l2_ioctl (fd, VIDIOC_QBUF, &buf) < 0)
445             {
446                 msg_Err (demux, "cannot queue buffer: %m");
447                 return -1;
448             }
449         }
450
451         enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
452         if (v4l2_ioctl (fd, VIDIOC_STREAMON, &buf_type) < 0)
453         {
454             msg_Err (demux, "cannot start streaming: %m");
455             return -1;
456         }
457
458         sys->io = IO_METHOD_MMAP;
459         entry = StreamThread;
460     }
461     else if (caps & V4L2_CAP_READWRITE)
462     {
463         sys->blocksize = fmt.fmt.pix.sizeimage;
464         sys->io = IO_METHOD_READ;
465         entry = ReadThread;
466     }
467     else
468     {
469         msg_Err (demux, "no supported I/O method");
470         return -1;
471     }
472
473     if (vlc_clone (&sys->thread, entry, demux, VLC_THREAD_PRIORITY_INPUT))
474         return -1;
475     return 0;
476 }
477
478 void DemuxClose( vlc_object_t *obj )
479 {
480     demux_t *demux = (demux_t *)obj;
481     demux_sys_t *sys = demux->p_sys;
482     int fd = sys->i_fd;
483
484     vlc_cancel (sys->thread);
485     vlc_join (sys->thread, NULL);
486
487     /* Stop video capture */
488     switch( sys->io )
489     {
490         case IO_METHOD_READ:
491             /* Nothing to do */
492             break;
493
494         case IO_METHOD_MMAP:
495         {
496             /* NOTE: Some buggy drivers hang if buffers are not unmapped before
497              * streamoff */
498             for (uint32_t i = 0; i < sys->bufc; i++)
499             {
500                 struct v4l2_buffer buf = {
501                     .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
502                     .memory = V4L2_MEMORY_MMAP,
503                 };
504                 v4l2_ioctl (fd, VIDIOC_DQBUF, &buf);
505                 v4l2_munmap (sys->bufv[i].start, sys->bufv[i].length);
506             }
507             enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
508             v4l2_ioctl( sys->i_fd, VIDIOC_STREAMOFF, &buf_type );
509             free (sys->bufv);
510             break;
511         }
512     }
513
514     ControlsDeinit( obj, sys->controls );
515     v4l2_close( fd );
516     free( sys );
517 }
518
519 static void *StreamThread (void *data)
520 {
521     demux_t *demux = data;
522     demux_sys_t *sys = demux->p_sys;
523     int fd = sys->i_fd;
524     struct pollfd ufd[1];
525
526     ufd[0].fd = fd;
527     ufd[0].events = POLLIN | POLLPRI;
528
529     for (;;)
530     {
531         /* Wait for data */
532         if (poll (ufd, 1, -1) == -1)
533         {
534            if (errno != EINTR)
535                msg_Err (demux, "poll error: %m");
536            continue;
537         }
538
539         int canc = vlc_savecancel ();
540         block_t *block = GrabVideo (VLC_OBJECT(demux), fd, sys->bufv);
541         if (block != NULL)
542         {
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);
547         }
548         vlc_restorecancel (canc);
549     }
550
551     assert (0);
552 }
553
554 static void *ReadThread (void *data)
555 {
556     demux_t *demux = data;
557     demux_sys_t *sys = demux->p_sys;
558     int fd = sys->i_fd;
559     struct pollfd ufd[1];
560
561     ufd[0].fd = fd;
562     ufd[0].events = POLLIN | POLLPRI;
563
564     for (;;)
565     {
566         /* Wait for data */
567         if (poll (ufd, 1, -1) == -1)
568         {
569            if (errno != EINTR)
570                msg_Err (demux, "poll error: %m");
571            continue;
572         }
573
574         block_t *block = block_Alloc (sys->blocksize);
575         if (unlikely(block == NULL))
576         {
577             msg_Err (demux, "read error: %m");
578             v4l2_read (fd, NULL, 0); /* discard frame */
579             continue;
580         }
581         block->i_pts = block->i_dts = mdate ();
582         block->i_flags |= sys->i_block_flags;
583
584         int canc = vlc_savecancel ();
585         ssize_t val = v4l2_read (fd, block->p_buffer, block->i_buffer);
586         if (val != -1)
587         {
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);
591         }
592         else
593             block_Release (block);
594         vlc_restorecancel (canc);
595     }
596     assert (0);
597 }
598
599 static int DemuxControl( demux_t *demux, int query, va_list args )
600 {
601     switch( query )
602     {
603         /* Special for access_demux */
604         case DEMUX_CAN_PAUSE:
605         case DEMUX_CAN_SEEK:
606         case DEMUX_CAN_CONTROL_PACE:
607             *va_arg( args, bool * ) = false;
608             return VLC_SUCCESS;
609
610         case DEMUX_GET_PTS_DELAY:
611             *va_arg(args,int64_t *) = INT64_C(1000)
612                 * var_InheritInteger( demux, "live-caching" );
613             return VLC_SUCCESS;
614
615         case DEMUX_GET_TIME:
616             *va_arg( args, int64_t * ) = mdate();
617             return VLC_SUCCESS;
618
619         /* TODO implement others */
620         default:
621             return VLC_EGENERIC;
622     }
623
624     return VLC_EGENERIC;
625 }