]> git.sesse.net Git - vlc/blob - modules/access/v4l2/video.c
access/stream_filter: add libarchive
[vlc] / modules / access / v4l2 / video.c
1 /*****************************************************************************
2  * video.c : Video4Linux2 input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002-2009 VLC authors and VideoLAN
5  * Copyright (C) 2011-2012 RĂ©mi Denis-Courmont
6  *
7  * Authors: Benjamin Pracht <bigben at videolan dot org>
8  *          Richard Hosking <richard at hovis dot net>
9  *          Antoine Cellerier <dionoea at videolan d.t org>
10  *          Dennis Lou <dlou99 at yahoo dot com>
11  *
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU Lesser General Public License as published by
14  * the Free Software Foundation; either version 2.1 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <assert.h>
32 #include <errno.h>
33 #include <sys/ioctl.h>
34 #include <sys/mman.h>
35
36 #include <vlc_common.h>
37 #include <vlc_block.h>
38
39 #include "v4l2.h"
40
41 static int SetupStandard (vlc_object_t *obj, int fd,
42                           const struct v4l2_input *restrict input,
43                           v4l2_std_id *restrict std)
44 {
45     if (!(input->capabilities & V4L2_IN_CAP_STD))
46     {
47         msg_Dbg (obj, "no video standard selection");
48         *std = V4L2_STD_UNKNOWN;
49         return 0;
50     }
51
52     *std = var_InheritStandard (obj, CFG_PREFIX"standard");
53     if (*std == V4L2_STD_UNKNOWN)
54     {
55         msg_Warn (obj, "video standard not set");
56
57         /* Grab the currently selected standard */
58         if (v4l2_ioctl (fd, VIDIOC_G_STD, std) < 0)
59             msg_Err (obj, "cannot get video standard");
60         return 0;
61     }
62     if (v4l2_ioctl (fd, VIDIOC_S_STD, std) < 0)
63     {
64         msg_Err (obj, "cannot set video standard 0x%"PRIx64": %s",
65                  (uint64_t)*std, vlc_strerror_c(errno));
66         return -1;
67     }
68     msg_Dbg (obj, "video standard set to 0x%"PRIx64":", (uint64_t)*std);
69     return 0;
70 }
71
72 static int SetupAudio (vlc_object_t *obj, int fd,
73                        const struct v4l2_input *restrict input)
74 {
75     if (input->audioset == 0)
76     {
77         msg_Dbg (obj, "no audio input available");
78         return 0;
79     }
80     msg_Dbg (obj, "available audio inputs: 0x%08"PRIX32, input->audioset);
81
82     uint32_t idx = var_InheritInteger (obj, CFG_PREFIX"audio-input");
83     if (idx == (uint32_t)-1)
84     {
85         msg_Dbg (obj, "no audio input selected");
86         return 0;
87     }
88     if (((1 << idx) & input->audioset) == 0)
89     {
90         msg_Warn (obj, "skipped unavailable audio input %"PRIu32, idx);
91         return -1;
92     }
93
94     /* TODO: Enumerate other selectable audio inputs. How to expose them? */
95     struct v4l2_audio enumaudio = { .index = idx };
96
97     if (v4l2_ioctl (fd, VIDIOC_ENUMAUDIO, &enumaudio) < 0)
98     {
99         msg_Err (obj, "cannot get audio input %"PRIu32" properties: %s", idx,
100                  vlc_strerror_c(errno));
101         return -1;
102     }
103
104     msg_Dbg (obj, "audio input %s (%"PRIu32") is %s"
105              " (capabilities: 0x%08"PRIX32")", enumaudio.name, enumaudio.index,
106              (enumaudio.capability & V4L2_AUDCAP_STEREO) ? "Stereo" : "Mono",
107              enumaudio.capability);
108     if (enumaudio.capability & V4L2_AUDCAP_AVL)
109         msg_Dbg (obj, " supports Automatic Volume Level");
110
111     /* TODO: AVL mode */
112     struct v4l2_audio audio = { .index = idx };
113
114     if (v4l2_ioctl (fd, VIDIOC_S_AUDIO, &audio) < 0)
115     {
116         msg_Err (obj, "cannot select audio input %"PRIu32": %s", idx,
117                  vlc_strerror_c(errno));
118         return -1;
119     }
120     msg_Dbg (obj, "selected audio input %"PRIu32, idx);
121     return 0;
122 }
123
124 int SetupTuner (vlc_object_t *obj, int fd, uint32_t idx)
125 {
126     struct v4l2_tuner tuner = { .index = idx };
127
128     if (v4l2_ioctl (fd, VIDIOC_G_TUNER, &tuner) < 0)
129     {
130         msg_Err (obj, "cannot get tuner %"PRIu32" properties: %s", idx,
131                  vlc_strerror_c(errno));
132         return -1;
133     }
134
135     /* NOTE: This is overkill. Only video devices currently work, so the
136      * type is always analog TV. */
137     const char *typename, *mult;
138     switch (tuner.type)
139     {
140         case V4L2_TUNER_RADIO:
141             typename = "Radio";
142             break;
143         case V4L2_TUNER_ANALOG_TV:
144             typename = "Analog TV";
145             break;
146         default:
147             typename = "unknown";
148     }
149     mult = (tuner.capability & V4L2_TUNER_CAP_LOW) ? "" : "k";
150
151     msg_Dbg (obj, "tuner %s (%"PRIu32") is %s", tuner.name, tuner.index,
152              typename);
153     msg_Dbg (obj, " ranges from %u.%u %sHz to %u.%u %sHz",
154              (tuner.rangelow * 125) >> 1, (tuner.rangelow & 1) * 5, mult,
155              (tuner.rangehigh * 125) >> 1, (tuner.rangehigh & 1) * 5,
156              mult);
157
158     /* TODO: only set video standard if the tuner requires it */
159
160     /* Configure the audio mode */
161     /* TODO: Ideally, L1 would be selected for stereo tuners, and L1_L2
162      * for mono tuners. When dual-mono is detected after tuning on a stereo
163      * tuner, we would fallback to L1_L2 too. Then we would flag dual-mono
164      * for the audio E/S. Unfortunately, we have no access to the audio E/S
165      * here (it belongs in the slave audio input...). */
166     tuner.audmode = var_InheritInteger (obj, CFG_PREFIX"tuner-audio-mode");
167     memset (tuner.reserved, 0, sizeof (tuner.reserved));
168
169     if (tuner.capability & V4L2_TUNER_CAP_LANG1)
170         msg_Dbg (obj, " supports primary audio language");
171     else if (tuner.audmode == V4L2_TUNER_MODE_LANG1)
172     {
173         msg_Warn (obj, " falling back to stereo mode");
174         tuner.audmode = V4L2_TUNER_MODE_STEREO;
175     }
176     if (tuner.capability & V4L2_TUNER_CAP_LANG2)
177         msg_Dbg (obj, " supports secondary audio language or program");
178     if (tuner.capability & V4L2_TUNER_CAP_STEREO)
179         msg_Dbg (obj, " supports stereo audio");
180     else if (tuner.audmode == V4L2_TUNER_MODE_STEREO)
181     {
182         msg_Warn (obj, " falling back to mono mode");
183         tuner.audmode = V4L2_TUNER_MODE_MONO;
184     }
185
186     if (v4l2_ioctl (fd, VIDIOC_S_TUNER, &tuner) < 0)
187     {
188         msg_Err (obj, "cannot set tuner %"PRIu32" audio mode: %s", idx,
189                  vlc_strerror_c(errno));
190         return -1;
191     }
192     msg_Dbg (obj, "tuner %"PRIu32" audio mode %u set", idx, tuner.audmode);
193
194     /* Tune to the requested frequency */
195     uint32_t freq = var_InheritInteger (obj, CFG_PREFIX"tuner-frequency");
196     if (freq != (uint32_t)-1)
197     {
198         struct v4l2_frequency frequency = {
199             .tuner = idx,
200             .type = tuner.type,
201             .frequency = freq * 2 / 125,
202         };
203
204         if (v4l2_ioctl (fd, VIDIOC_S_FREQUENCY, &frequency) < 0)
205         {
206             msg_Err (obj, "cannot tune tuner %"PRIu32
207                      " to frequency %u %sHz: %s", idx, freq, mult,
208                      vlc_strerror_c(errno));
209             return -1;
210         }
211         msg_Dbg (obj, "tuner %"PRIu32" tuned to frequency %"PRIu32" %sHz",
212                  idx, freq, mult);
213     }
214     else
215         msg_Dbg (obj, "tuner not tuned");
216     return 0;
217 }
218
219 static int ResetCrop (vlc_object_t *obj, int fd)
220 {
221     struct v4l2_cropcap cropcap = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
222
223     /* In theory, this ioctl() must work for all video capture devices.
224      * In practice, it does not. */
225     if (v4l2_ioctl (fd, VIDIOC_CROPCAP, &cropcap) < 0)
226     {
227         msg_Dbg (obj, "cannot get cropping properties: %s",
228                  vlc_strerror_c(errno));
229         return 0;
230     }
231
232     /* Reset to the default cropping rectangle */
233     struct v4l2_crop crop = {
234         .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
235         .c = cropcap.defrect,
236     };
237
238     if (v4l2_ioctl (fd, VIDIOC_S_CROP, &crop) < 0)
239     {
240         msg_Warn (obj, "cannot reset cropping limits: %s",
241                   vlc_strerror_c(errno));
242         return -1;
243     }
244     return 0;
245 }
246
247 int SetupInput (vlc_object_t *obj, int fd, v4l2_std_id *std)
248 {
249     struct v4l2_input input;
250
251     input.index = var_InheritInteger (obj, CFG_PREFIX"input");
252     if (v4l2_ioctl (fd, VIDIOC_ENUMINPUT, &input) < 0)
253     {
254         msg_Err (obj, "invalid video input %"PRIu32": %s", input.index,
255                  vlc_strerror_c(errno));
256         return -1;
257     }
258
259     const char *typename = "unknown";
260     switch (input.type)
261     {
262         case V4L2_INPUT_TYPE_TUNER:
263             typename = "tuner";
264             break;
265         case V4L2_INPUT_TYPE_CAMERA:
266             typename = "camera";
267             break;
268     }
269
270     msg_Dbg (obj, "video input %s (%"PRIu32") is %s", input.name,
271              input.index, typename);
272
273     /* Select input */
274     if (v4l2_ioctl (fd, VIDIOC_S_INPUT, &input.index) < 0)
275     {
276         msg_Err (obj, "cannot select input %"PRIu32": %s", input.index,
277                  vlc_strerror_c(errno));
278         return -1;
279     }
280     msg_Dbg (obj, "selected input %"PRIu32, input.index);
281
282     SetupStandard (obj, fd, &input, std);
283
284     switch (input.type)
285     {
286         case V4L2_INPUT_TYPE_TUNER:
287             msg_Dbg (obj, "tuning required: tuner %"PRIu32, input.tuner);
288             SetupTuner (obj, fd, input.tuner);
289             break;
290         case V4L2_INPUT_TYPE_CAMERA:
291             msg_Dbg (obj, "no tuning required (analog baseband input)");
292             break;
293         default:
294             msg_Err (obj, "unknown input tuning type %"PRIu32, input.type);
295             break; // hopefully we can stream regardless...
296     }
297
298     SetupAudio (obj, fd, &input);
299     return 0;
300 }
301
302 /** Compares two V4L2 fractions. */
303 static int64_t fcmp (const struct v4l2_fract *a,
304                      const struct v4l2_fract *b)
305 {
306     return (uint64_t)a->numerator * b->denominator
307          - (uint64_t)b->numerator * a->denominator;
308 }
309
310 static const struct v4l2_fract infinity = { 1, 0 };
311 static const struct v4l2_fract zero = { 0, 1 };
312
313 /**
314  * Finds the highest frame rate up to a specific limit possible with a certain
315  * V4L2 format.
316  * @param fmt V4L2 capture format [IN]
317  * @param min_it minimum frame internal [IN]
318  * @param it V4L2 frame interval [OUT]
319  * @return 0 on success, -1 on error.
320  */
321 static int FindMaxRate (vlc_object_t *obj, int fd,
322                         const struct v4l2_format *restrict fmt,
323                         const struct v4l2_fract *restrict min_it,
324                         struct v4l2_fract *restrict it)
325 {
326     struct v4l2_frmivalenum fie = {
327         .pixel_format = fmt->fmt.pix.pixelformat,
328         .width = fmt->fmt.pix.width,
329         .height = fmt->fmt.pix.height,
330     };
331     /* Mind that maximum rate means minimum interval */
332
333     if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &fie) < 0)
334     {
335         msg_Dbg (obj, "  unknown frame intervals: %s", vlc_strerror_c(errno));
336         /* Frame intervals cannot be enumerated. Set the format and then
337          * get the streaming parameters to figure out the default frame
338          * interval. This is not necessarily the maximum though. */
339         struct v4l2_format dummy_fmt = *fmt;
340         struct v4l2_streamparm parm = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
341
342         if (v4l2_ioctl (fd, VIDIOC_S_FMT, &dummy_fmt) < 0
343          || v4l2_ioctl (fd, VIDIOC_G_PARM, &parm) < 0)
344         {
345             *it = infinity;
346             return -1;
347         }
348
349         *it = parm.parm.capture.timeperframe;
350         msg_Dbg (obj, "  %s frame interval: %"PRIu32"/%"PRIu32,
351                  (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)
352                  ? "default" : "constant", it->numerator, it->denominator);
353     }
354     else
355     switch (fie.type)
356     {
357         case V4L2_FRMIVAL_TYPE_DISCRETE:
358             *it = infinity;
359             do
360             {
361                 if (fcmp (&fie.discrete, min_it) >= 0
362                  && fcmp (&fie.discrete, it) < 0)
363                     *it = fie.discrete;
364                 fie.index++;
365             }
366             while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &fie) >= 0);
367
368             msg_Dbg (obj, "  %s frame interval: %"PRIu32"/%"PRIu32,
369                      "discrete", it->numerator, it->denominator);
370             break;
371
372         case V4L2_FRMIVAL_TYPE_STEPWISE:
373         case V4L2_FRMIVAL_TYPE_CONTINUOUS:
374             msg_Dbg (obj, "  frame intervals from %"PRIu32"/%"PRIu32
375                      " to %"PRIu32"/%"PRIu32" supported",
376                      fie.stepwise.min.numerator, fie.stepwise.min.denominator,
377                      fie.stepwise.max.numerator, fie.stepwise.max.denominator);
378             if (fie.type == V4L2_FRMIVAL_TYPE_STEPWISE)
379                 msg_Dbg (obj, "  with %"PRIu32"/%"PRIu32" step",
380                          fie.stepwise.step.numerator,
381                          fie.stepwise.step.denominator);
382
383             if (fcmp (&fie.stepwise.max, min_it) < 0)
384             {
385                 *it = infinity;
386                 return -1;
387             }
388
389             if (fcmp (&fie.stepwise.min, min_it) >= 0)
390             {
391                 *it = fie.stepwise.min;
392                 break;
393             }
394
395             if (fie.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)
396             {
397                 *it = *min_it;
398                 break;
399             }
400
401             it->numerator *= fie.stepwise.step.denominator;
402             it->denominator *= fie.stepwise.step.denominator;
403             while (fcmp (it, min_it) < 0)
404                 it->numerator += fie.stepwise.step.numerator;
405             break;
406     }
407     return 0;
408 }
409
410 #undef SetupFormat
411 /**
412  * Finds the best possible frame rate and resolution.
413  * @param fourcc pixel format
414  * @param fmt V4L2 capture format [OUT]
415  * @param parm V4L2 capture streaming parameters [OUT]
416  * @return 0 on success, -1 on failure.
417  */
418 int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc,
419                  struct v4l2_format *restrict fmt,
420                  struct v4l2_streamparm *restrict parm)
421 {
422     memset (fmt, 0, sizeof (*fmt));
423     fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
424     memset (parm, 0, sizeof (*parm));
425     parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
426
427     if (v4l2_ioctl (fd, VIDIOC_G_FMT, fmt) < 0)
428     {
429         msg_Err (obj, "cannot get default format: %s", vlc_strerror_c(errno));
430         return -1;
431     }
432     fmt->fmt.pix.pixelformat = fourcc;
433
434     struct v4l2_frmsizeenum fse = {
435         .pixel_format = fourcc,
436     };
437     struct v4l2_fract best_it = infinity, min_it;
438     uint64_t best_area = 0;
439
440     if (var_InheritURational(obj, &min_it.denominator, &min_it.numerator,
441                              CFG_PREFIX"fps") == VLC_SUCCESS)
442         msg_Dbg (obj, " requested frame internal: %"PRIu32"/%"PRIu32,
443                  min_it.numerator, min_it.denominator);
444     else
445         min_it = zero;
446
447     uint32_t width = var_InheritInteger (obj, CFG_PREFIX"width");
448     uint32_t height = var_InheritInteger (obj, CFG_PREFIX"height");
449     if (width > 0 && height > 0)
450     {
451         fmt->fmt.pix.width = width;
452         fmt->fmt.pix.height = height;
453         msg_Dbg (obj, " requested frame size: %"PRIu32"x%"PRIu32,
454                  width, height);
455         FindMaxRate (obj, fd, fmt, &min_it, &best_it);
456     }
457     else
458     if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &fse) < 0)
459     {
460         /* Fallback to current format, try to maximize frame rate */
461         msg_Dbg (obj, " unknown frame sizes: %s", vlc_strerror_c(errno));
462         msg_Dbg (obj, " current frame size: %"PRIu32"x%"PRIu32,
463                  fmt->fmt.pix.width, fmt->fmt.pix.height);
464         FindMaxRate (obj, fd, fmt, &min_it, &best_it);
465     }
466     else
467     switch (fse.type)
468     {
469         case V4L2_FRMSIZE_TYPE_DISCRETE:
470             do
471             {
472                 struct v4l2_fract cur_it;
473
474                 msg_Dbg (obj, " frame size %"PRIu32"x%"PRIu32,
475                          fse.discrete.width, fse.discrete.height);
476                 FindMaxRate (obj, fd, fmt, &min_it, &cur_it);
477
478                 int64_t c = fcmp (&cur_it, &best_it);
479                 uint64_t area = fse.discrete.width * fse.discrete.height;
480                 if (c < 0 || (c == 0 && area > best_area))
481                 {
482                     best_it = cur_it;
483                     best_area = area;
484                     fmt->fmt.pix.width = fse.discrete.width;
485                     fmt->fmt.pix.height = fse.discrete.height;
486                 }
487
488                 fse.index++;
489             }
490             while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &fse) >= 0);
491
492             msg_Dbg (obj, " best discrete frame size: %"PRIu32"x%"PRIu32,
493                      fmt->fmt.pix.width, fmt->fmt.pix.height);
494             break;
495
496         case V4L2_FRMSIZE_TYPE_STEPWISE:
497         case V4L2_FRMSIZE_TYPE_CONTINUOUS:
498             msg_Dbg (obj, " frame sizes from %"PRIu32"x%"PRIu32" to "
499                      "%"PRIu32"x%"PRIu32" supported",
500                      fse.stepwise.min_width, fse.stepwise.min_height,
501                      fse.stepwise.max_width, fse.stepwise.max_height);
502             if (fse.type == V4L2_FRMSIZE_TYPE_STEPWISE)
503                 msg_Dbg (obj, "  with %"PRIu32"x%"PRIu32" steps",
504                          fse.stepwise.step_width, fse.stepwise.step_height);
505
506             /* FIXME: slow and dumb */
507             for (uint32_t width =  fse.stepwise.min_width;
508                           width <= fse.stepwise.max_width;
509                           width += fse.stepwise.step_width)
510                 for (uint32_t height =  fse.stepwise.min_height;
511                               height <= fse.stepwise.max_width;
512                               height += fse.stepwise.step_height)
513                 {
514                     struct v4l2_fract cur_it;
515
516                     FindMaxRate (obj, fd, fmt, &min_it, &cur_it);
517
518                     int64_t c = fcmp (&cur_it, &best_it);
519                     uint64_t area = width * height;
520
521                     if (c < 0 || (c == 0 && area > best_area))
522                     {
523                         best_it = cur_it;
524                         best_area = area;
525                         fmt->fmt.pix.width = width;
526                         fmt->fmt.pix.height = height;
527                     }
528                 }
529
530             msg_Dbg (obj, " best frame size: %"PRIu32"x%"PRIu32,
531                      fmt->fmt.pix.width, fmt->fmt.pix.height);
532             break;
533     }
534
535     /* Set the final format */
536     if (v4l2_ioctl (fd, VIDIOC_S_FMT, fmt) < 0)
537     {
538         msg_Err (obj, "cannot set format: %s", vlc_strerror_c(errno));
539         return -1;
540     }
541
542     /* Now that the final format is set, fetch and override parameters */
543     if (v4l2_ioctl (fd, VIDIOC_G_PARM, parm) < 0)
544     {
545         msg_Err (obj, "cannot get streaming parameters: %s",
546                  vlc_strerror_c(errno));
547         memset (parm, 0, sizeof (*parm));
548         parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
549     }
550     parm->parm.capture.capturemode = 0; /* normal video mode */
551     parm->parm.capture.extendedmode = 0;
552     if (best_it.denominator != 0)
553         parm->parm.capture.timeperframe = best_it;
554     if (v4l2_ioctl (fd, VIDIOC_S_PARM, parm) < 0)
555         msg_Warn (obj, "cannot set streaming parameters: %s",
556                   vlc_strerror_c(errno));
557
558     ResetCrop (obj, fd); /* crop depends on frame size */
559
560     return 0;
561 }
562
563 mtime_t GetBufferPTS (const struct v4l2_buffer *buf)
564 {
565     mtime_t pts;
566
567     switch (buf->flags & V4L2_BUF_FLAG_TIMESTAMP_MASK)
568     {
569         case V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC:
570             pts = (buf->timestamp.tv_sec * CLOCK_FREQ)
571                  + buf->timestamp.tv_usec;
572             static_assert (CLOCK_FREQ == 1000000, "Clock unit mismatch");
573             break;
574         case V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN:
575         default:
576             pts = mdate ();
577             break;
578     }
579     return pts;
580 }
581
582 /*****************************************************************************
583  * GrabVideo: Grab a video frame
584  *****************************************************************************/
585 block_t *GrabVideo (vlc_object_t *demux, int fd,
586                     const struct buffer_t *restrict bufv)
587 {
588     struct v4l2_buffer buf = {
589         .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
590         .memory = V4L2_MEMORY_MMAP,
591     };
592
593     /* Wait for next frame */
594     if (v4l2_ioctl (fd, VIDIOC_DQBUF, &buf) < 0)
595     {
596         switch (errno)
597         {
598             case EAGAIN:
599                 return NULL;
600             case EIO:
601                 /* Could ignore EIO, see spec. */
602                 /* fall through */
603             default:
604                 msg_Err (demux, "dequeue error: %s", vlc_strerror_c(errno));
605                 return NULL;
606         }
607     }
608
609     /* Copy frame */
610     block_t *block = block_Alloc (buf.bytesused);
611     if (unlikely(block == NULL))
612         return NULL;
613     block->i_pts = block->i_dts = GetBufferPTS (&buf);
614     memcpy (block->p_buffer, bufv[buf.index].start, buf.bytesused);
615
616     /* Unlock */
617     if (v4l2_ioctl (fd, VIDIOC_QBUF, &buf) < 0)
618     {
619         msg_Err (demux, "queue error: %s", vlc_strerror_c(errno));
620         block_Release (block);
621         return NULL;
622     }
623     return block;
624 }
625
626 /**
627  * Allocates user pointer buffers, and start streaming.
628  */
629 int StartUserPtr (vlc_object_t *obj, int fd)
630 {
631     struct v4l2_requestbuffers reqbuf = {
632         .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
633         .memory = V4L2_MEMORY_USERPTR,
634         .count = 2,
635     };
636
637     if (v4l2_ioctl (fd, VIDIOC_REQBUFS, &reqbuf) < 0)
638     {
639         msg_Dbg (obj, "cannot reserve user buffers: %s",
640                  vlc_strerror_c(errno));
641         return -1;
642     }
643     if (v4l2_ioctl (fd, VIDIOC_STREAMON, &reqbuf.type) < 0)
644     {
645         msg_Err (obj, "cannot start streaming: %s", vlc_strerror_c(errno));
646         return -1;
647     }
648     return 0;
649 }
650
651 /**
652  * Allocates memory-mapped buffers, queues them and start streaming.
653  * @param n requested buffers count [IN], allocated buffers count [OUT]
654  * @return array of allocated buffers (use free()), or NULL on error.
655  */
656 struct buffer_t *StartMmap (vlc_object_t *obj, int fd, uint32_t *restrict n)
657 {
658     struct v4l2_requestbuffers req = {
659         .count = *n,
660         .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
661         .memory = V4L2_MEMORY_MMAP,
662     };
663
664     if (v4l2_ioctl (fd, VIDIOC_REQBUFS, &req) < 0)
665     {
666         msg_Err (obj, "cannot allocate buffers: %s", vlc_strerror_c(errno));
667         return NULL;
668     }
669
670     if (req.count < 2)
671     {
672         msg_Err (obj, "cannot allocate enough buffers");
673         return NULL;
674     }
675
676     struct buffer_t *bufv = malloc (req.count * sizeof (*bufv));
677     if (unlikely(bufv == NULL))
678         return NULL;
679
680     uint32_t bufc = 0;
681     while (bufc < req.count)
682     {
683         struct v4l2_buffer buf = {
684             .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
685             .memory = V4L2_MEMORY_MMAP,
686             .index = bufc,
687         };
688
689         if (v4l2_ioctl (fd, VIDIOC_QUERYBUF, &buf) < 0)
690         {
691             msg_Err (obj, "cannot query buffer %"PRIu32": %s", bufc,
692                      vlc_strerror_c(errno));
693             goto error;
694         }
695
696         bufv[bufc].start = v4l2_mmap (NULL, buf.length, PROT_READ | PROT_WRITE,
697                                       MAP_SHARED, fd, buf.m.offset);
698         if (bufv[bufc].start == MAP_FAILED)
699         {
700             msg_Err (obj, "cannot map buffer %"PRIu32": %s", bufc,
701                      vlc_strerror_c(errno));
702             goto error;
703         }
704         bufv[bufc].length = buf.length;
705         bufc++;
706
707         /* Some drivers refuse to queue buffers before they are mapped. Bug? */
708         if (v4l2_ioctl (fd, VIDIOC_QBUF, &buf) < 0)
709         {
710             msg_Err (obj, "cannot queue buffer %"PRIu32": %s", bufc,
711                      vlc_strerror_c(errno));
712             goto error;
713         }
714     }
715
716     enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
717     if (v4l2_ioctl (fd, VIDIOC_STREAMON, &type) < 0)
718     {
719         msg_Err (obj, "cannot start streaming: %s", vlc_strerror_c(errno));
720         goto error;
721     }
722     *n = bufc;
723     return bufv;
724 error:
725     StopMmap (fd, bufv, bufc);
726     return NULL;
727 }
728
729 void StopMmap (int fd, struct buffer_t *bufv, uint32_t bufc)
730 {
731     enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
732
733     /* STREAMOFF implicitly dequeues all buffers */
734     v4l2_ioctl (fd, VIDIOC_STREAMOFF, &type);
735     for (uint32_t i = 0; i < bufc; i++)
736         v4l2_munmap (bufv[i].start, bufv[i].length);
737     free (bufv);
738 }