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
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>
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.
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.
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 *****************************************************************************/
33 #include <sys/ioctl.h>
36 #include <vlc_common.h>
37 #include <vlc_block.h>
41 static int SetupStandard (vlc_object_t
*obj
, int fd
,
42 const struct v4l2_input
*restrict input
,
43 v4l2_std_id
*restrict std
)
45 if (!(input
->capabilities
& V4L2_IN_CAP_STD
))
47 msg_Dbg (obj
, "no video standard selection");
48 *std
= V4L2_STD_UNKNOWN
;
52 *std
= var_InheritStandard (obj
, CFG_PREFIX
"standard");
53 if (*std
== V4L2_STD_UNKNOWN
)
55 msg_Warn (obj
, "video standard not set");
57 /* Grab the currently selected standard */
58 if (v4l2_ioctl (fd
, VIDIOC_G_STD
, std
) < 0)
59 msg_Err (obj
, "cannot get video standard");
62 if (v4l2_ioctl (fd
, VIDIOC_S_STD
, std
) < 0)
64 msg_Err (obj
, "cannot set video standard 0x%"PRIx64
": %s",
65 (uint64_t)*std
, vlc_strerror_c(errno
));
68 msg_Dbg (obj
, "video standard set to 0x%"PRIx64
":", (uint64_t)*std
);
72 static int SetupAudio (vlc_object_t
*obj
, int fd
,
73 const struct v4l2_input
*restrict input
)
75 if (input
->audioset
== 0)
77 msg_Dbg (obj
, "no audio input available");
80 msg_Dbg (obj
, "available audio inputs: 0x%08"PRIX32
, input
->audioset
);
82 uint32_t idx
= var_InheritInteger (obj
, CFG_PREFIX
"audio-input");
83 if (idx
== (uint32_t)-1)
85 msg_Dbg (obj
, "no audio input selected");
88 if (((1 << idx
) & input
->audioset
) == 0)
90 msg_Warn (obj
, "skipped unavailable audio input %"PRIu32
, idx
);
94 /* TODO: Enumerate other selectable audio inputs. How to expose them? */
95 struct v4l2_audio enumaudio
= { .index
= idx
};
97 if (v4l2_ioctl (fd
, VIDIOC_ENUMAUDIO
, &enumaudio
) < 0)
99 msg_Err (obj
, "cannot get audio input %"PRIu32
" properties: %s", idx
,
100 vlc_strerror_c(errno
));
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");
112 struct v4l2_audio audio
= { .index
= idx
};
114 if (v4l2_ioctl (fd
, VIDIOC_S_AUDIO
, &audio
) < 0)
116 msg_Err (obj
, "cannot select audio input %"PRIu32
": %s", idx
,
117 vlc_strerror_c(errno
));
120 msg_Dbg (obj
, "selected audio input %"PRIu32
, idx
);
124 int SetupTuner (vlc_object_t
*obj
, int fd
, uint32_t idx
)
126 struct v4l2_tuner tuner
= { .index
= idx
};
128 if (v4l2_ioctl (fd
, VIDIOC_G_TUNER
, &tuner
) < 0)
130 msg_Err (obj
, "cannot get tuner %"PRIu32
" properties: %s", idx
,
131 vlc_strerror_c(errno
));
135 /* NOTE: This is overkill. Only video devices currently work, so the
136 * type is always analog TV. */
137 const char *typename
, *mult
;
140 case V4L2_TUNER_RADIO
:
143 case V4L2_TUNER_ANALOG_TV
:
144 typename
= "Analog TV";
147 typename
= "unknown";
149 mult
= (tuner
.capability
& V4L2_TUNER_CAP_LOW
) ? "" : "k";
151 msg_Dbg (obj
, "tuner %s (%"PRIu32
") is %s", tuner
.name
, tuner
.index
,
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,
158 /* TODO: only set video standard if the tuner requires it */
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
));
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
)
173 msg_Warn (obj
, " falling back to stereo mode");
174 tuner
.audmode
= V4L2_TUNER_MODE_STEREO
;
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
)
182 msg_Warn (obj
, " falling back to mono mode");
183 tuner
.audmode
= V4L2_TUNER_MODE_MONO
;
186 if (v4l2_ioctl (fd
, VIDIOC_S_TUNER
, &tuner
) < 0)
188 msg_Err (obj
, "cannot set tuner %"PRIu32
" audio mode: %s", idx
,
189 vlc_strerror_c(errno
));
192 msg_Dbg (obj
, "tuner %"PRIu32
" audio mode %u set", idx
, tuner
.audmode
);
194 /* Tune to the requested frequency */
195 uint32_t freq
= var_InheritInteger (obj
, CFG_PREFIX
"tuner-frequency");
196 if (freq
!= (uint32_t)-1)
198 struct v4l2_frequency frequency
= {
201 .frequency
= freq
* 2 / 125,
204 if (v4l2_ioctl (fd
, VIDIOC_S_FREQUENCY
, &frequency
) < 0)
206 msg_Err (obj
, "cannot tune tuner %"PRIu32
207 " to frequency %u %sHz: %s", idx
, freq
, mult
,
208 vlc_strerror_c(errno
));
211 msg_Dbg (obj
, "tuner %"PRIu32
" tuned to frequency %"PRIu32
" %sHz",
215 msg_Dbg (obj
, "tuner not tuned");
219 static int ResetCrop (vlc_object_t
*obj
, int fd
)
221 struct v4l2_cropcap cropcap
= { .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
};
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)
227 msg_Dbg (obj
, "cannot get cropping properties: %s",
228 vlc_strerror_c(errno
));
232 /* Reset to the default cropping rectangle */
233 struct v4l2_crop crop
= {
234 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
,
235 .c
= cropcap
.defrect
,
238 if (v4l2_ioctl (fd
, VIDIOC_S_CROP
, &crop
) < 0)
240 msg_Warn (obj
, "cannot reset cropping limits: %s",
241 vlc_strerror_c(errno
));
247 int SetupInput (vlc_object_t
*obj
, int fd
, v4l2_std_id
*std
)
249 struct v4l2_input input
;
251 input
.index
= var_InheritInteger (obj
, CFG_PREFIX
"input");
252 if (v4l2_ioctl (fd
, VIDIOC_ENUMINPUT
, &input
) < 0)
254 msg_Err (obj
, "invalid video input %"PRIu32
": %s", input
.index
,
255 vlc_strerror_c(errno
));
259 const char *typename
= "unknown";
262 case V4L2_INPUT_TYPE_TUNER
:
265 case V4L2_INPUT_TYPE_CAMERA
:
270 msg_Dbg (obj
, "video input %s (%"PRIu32
") is %s", input
.name
,
271 input
.index
, typename
);
274 if (v4l2_ioctl (fd
, VIDIOC_S_INPUT
, &input
.index
) < 0)
276 msg_Err (obj
, "cannot select input %"PRIu32
": %s", input
.index
,
277 vlc_strerror_c(errno
));
280 msg_Dbg (obj
, "selected input %"PRIu32
, input
.index
);
282 SetupStandard (obj
, fd
, &input
, std
);
286 case V4L2_INPUT_TYPE_TUNER
:
287 msg_Dbg (obj
, "tuning required: tuner %"PRIu32
, input
.tuner
);
288 SetupTuner (obj
, fd
, input
.tuner
);
290 case V4L2_INPUT_TYPE_CAMERA
:
291 msg_Dbg (obj
, "no tuning required (analog baseband input)");
294 msg_Err (obj
, "unknown input tuning type %"PRIu32
, input
.type
);
295 break; // hopefully we can stream regardless...
298 SetupAudio (obj
, fd
, &input
);
302 /** Compares two V4L2 fractions. */
303 static int64_t fcmp (const struct v4l2_fract
*a
,
304 const struct v4l2_fract
*b
)
306 return (uint64_t)a
->numerator
* b
->denominator
307 - (uint64_t)b
->numerator
* a
->denominator
;
310 static const struct v4l2_fract infinity
= { 1, 0 };
311 static const struct v4l2_fract zero
= { 0, 1 };
314 * Finds the highest frame rate up to a specific limit possible with a certain
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.
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
)
326 struct v4l2_frmivalenum fie
= {
327 .pixel_format
= fmt
->fmt
.pix
.pixelformat
,
328 .width
= fmt
->fmt
.pix
.width
,
329 .height
= fmt
->fmt
.pix
.height
,
331 /* Mind that maximum rate means minimum interval */
333 if (v4l2_ioctl (fd
, VIDIOC_ENUM_FRAMEINTERVALS
, &fie
) < 0)
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
};
342 if (v4l2_ioctl (fd
, VIDIOC_S_FMT
, &dummy_fmt
) < 0
343 || v4l2_ioctl (fd
, VIDIOC_G_PARM
, &parm
) < 0)
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
);
357 case V4L2_FRMIVAL_TYPE_DISCRETE
:
361 if (fcmp (&fie
.discrete
, min_it
) >= 0
362 && fcmp (&fie
.discrete
, it
) < 0)
366 while (v4l2_ioctl (fd
, VIDIOC_ENUM_FRAMEINTERVALS
, &fie
) >= 0);
368 msg_Dbg (obj
, " %s frame interval: %"PRIu32
"/%"PRIu32
,
369 "discrete", it
->numerator
, it
->denominator
);
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
);
383 if (fcmp (&fie
.stepwise
.max
, min_it
) < 0)
389 if (fcmp (&fie
.stepwise
.min
, min_it
) >= 0)
391 *it
= fie
.stepwise
.min
;
395 if (fie
.type
== V4L2_FRMIVAL_TYPE_CONTINUOUS
)
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
;
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.
418 int SetupFormat (vlc_object_t
*obj
, int fd
, uint32_t fourcc
,
419 struct v4l2_format
*restrict fmt
,
420 struct v4l2_streamparm
*restrict parm
)
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
;
427 if (v4l2_ioctl (fd
, VIDIOC_G_FMT
, fmt
) < 0)
429 msg_Err (obj
, "cannot get default format: %s", vlc_strerror_c(errno
));
432 fmt
->fmt
.pix
.pixelformat
= fourcc
;
434 struct v4l2_frmsizeenum fse
= {
435 .pixel_format
= fourcc
,
437 struct v4l2_fract best_it
= infinity
, min_it
;
438 uint64_t best_area
= 0;
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
);
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)
451 fmt
->fmt
.pix
.width
= width
;
452 fmt
->fmt
.pix
.height
= height
;
453 msg_Dbg (obj
, " requested frame size: %"PRIu32
"x%"PRIu32
,
455 FindMaxRate (obj
, fd
, fmt
, &min_it
, &best_it
);
458 if (v4l2_ioctl (fd
, VIDIOC_ENUM_FRAMESIZES
, &fse
) < 0)
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
);
469 case V4L2_FRMSIZE_TYPE_DISCRETE
:
472 struct v4l2_fract cur_it
;
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
);
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
))
484 fmt
->fmt
.pix
.width
= fse
.discrete
.width
;
485 fmt
->fmt
.pix
.height
= fse
.discrete
.height
;
490 while (v4l2_ioctl (fd
, VIDIOC_ENUM_FRAMESIZES
, &fse
) >= 0);
492 msg_Dbg (obj
, " best discrete frame size: %"PRIu32
"x%"PRIu32
,
493 fmt
->fmt
.pix
.width
, fmt
->fmt
.pix
.height
);
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
);
506 /* FIXME: slow and dumb */
507 for (width
= fse
.stepwise
.min_width
;
508 width
<= fse
.stepwise
.max_width
;
509 width
+= fse
.stepwise
.step_width
)
510 for (height
= fse
.stepwise
.min_height
;
511 height
<= fse
.stepwise
.max_height
;
512 height
+= fse
.stepwise
.step_height
)
514 struct v4l2_fract cur_it
;
516 FindMaxRate (obj
, fd
, fmt
, &min_it
, &cur_it
);
518 int64_t c
= fcmp (&cur_it
, &best_it
);
519 uint64_t area
= width
* height
;
521 if (c
< 0 || (c
== 0 && area
> best_area
))
525 fmt
->fmt
.pix
.width
= width
;
526 fmt
->fmt
.pix
.height
= height
;
530 msg_Dbg (obj
, " best frame size: %"PRIu32
"x%"PRIu32
,
531 fmt
->fmt
.pix
.width
, fmt
->fmt
.pix
.height
);
535 /* Set the final format */
536 if (v4l2_ioctl (fd
, VIDIOC_S_FMT
, fmt
) < 0)
538 msg_Err (obj
, "cannot set format: %s", vlc_strerror_c(errno
));
542 /* Now that the final format is set, fetch and override parameters */
543 if (v4l2_ioctl (fd
, VIDIOC_G_PARM
, parm
) < 0)
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
;
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
));
558 ResetCrop (obj
, fd
); /* crop depends on frame size */
563 mtime_t
GetBufferPTS (const struct v4l2_buffer
*buf
)
567 switch (buf
->flags
& V4L2_BUF_FLAG_TIMESTAMP_MASK
)
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");
574 case V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN
:
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
)
588 struct v4l2_buffer buf
= {
589 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
,
590 .memory
= V4L2_MEMORY_MMAP
,
593 /* Wait for next frame */
594 if (v4l2_ioctl (fd
, VIDIOC_DQBUF
, &buf
) < 0)
601 /* Could ignore EIO, see spec. */
604 msg_Err (demux
, "dequeue error: %s", vlc_strerror_c(errno
));
610 block_t
*block
= block_Alloc (buf
.bytesused
);
611 if (unlikely(block
== NULL
))
613 block
->i_pts
= block
->i_dts
= GetBufferPTS (&buf
);
614 memcpy (block
->p_buffer
, bufv
[buf
.index
].start
, buf
.bytesused
);
617 if (v4l2_ioctl (fd
, VIDIOC_QBUF
, &buf
) < 0)
619 msg_Err (demux
, "queue error: %s", vlc_strerror_c(errno
));
620 block_Release (block
);
627 * Allocates user pointer buffers, and start streaming.
629 int StartUserPtr (vlc_object_t
*obj
, int fd
)
631 struct v4l2_requestbuffers reqbuf
= {
632 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
,
633 .memory
= V4L2_MEMORY_USERPTR
,
637 if (v4l2_ioctl (fd
, VIDIOC_REQBUFS
, &reqbuf
) < 0)
639 msg_Dbg (obj
, "cannot reserve user buffers: %s",
640 vlc_strerror_c(errno
));
643 if (v4l2_ioctl (fd
, VIDIOC_STREAMON
, &reqbuf
.type
) < 0)
645 msg_Err (obj
, "cannot start streaming: %s", vlc_strerror_c(errno
));
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.
656 struct buffer_t
*StartMmap (vlc_object_t
*obj
, int fd
, uint32_t *restrict n
)
658 struct v4l2_requestbuffers req
= {
660 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
,
661 .memory
= V4L2_MEMORY_MMAP
,
664 if (v4l2_ioctl (fd
, VIDIOC_REQBUFS
, &req
) < 0)
666 msg_Err (obj
, "cannot allocate buffers: %s", vlc_strerror_c(errno
));
672 msg_Err (obj
, "cannot allocate enough buffers");
676 struct buffer_t
*bufv
= vlc_alloc (req
.count
, sizeof (*bufv
));
677 if (unlikely(bufv
== NULL
))
681 while (bufc
< req
.count
)
683 struct v4l2_buffer buf
= {
684 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
,
685 .memory
= V4L2_MEMORY_MMAP
,
689 if (v4l2_ioctl (fd
, VIDIOC_QUERYBUF
, &buf
) < 0)
691 msg_Err (obj
, "cannot query buffer %"PRIu32
": %s", bufc
,
692 vlc_strerror_c(errno
));
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
)
700 msg_Err (obj
, "cannot map buffer %"PRIu32
": %s", bufc
,
701 vlc_strerror_c(errno
));
704 bufv
[bufc
].length
= buf
.length
;
707 /* Some drivers refuse to queue buffers before they are mapped. Bug? */
708 if (v4l2_ioctl (fd
, VIDIOC_QBUF
, &buf
) < 0)
710 msg_Err (obj
, "cannot queue buffer %"PRIu32
": %s", bufc
,
711 vlc_strerror_c(errno
));
716 enum v4l2_buf_type type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
717 if (v4l2_ioctl (fd
, VIDIOC_STREAMON
, &type
) < 0)
719 msg_Err (obj
, "cannot start streaming: %s", vlc_strerror_c(errno
));
725 StopMmap (fd
, bufv
, bufc
);
729 void StopMmap (int fd
, struct buffer_t
*bufv
, uint32_t bufc
)
731 enum v4l2_buf_type type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
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
);