33 #undef __STRICT_ANSI__ //workaround due to broken kernel headers
38 #include <sys/ioctl.h>
41 #if HAVE_SYS_VIDEOIO_H
42 #include <sys/videoio.h>
45 #include <asm/types.h>
47 #include <linux/videodev2.h>
62 #define v4l2_open open
63 #define v4l2_close close
65 #define v4l2_ioctl ioctl
66 #define v4l2_read read
67 #define v4l2_mmap mmap
68 #define v4l2_munmap munmap
73 #define V4L_ALLFORMATS 3
74 #define V4L_RAWFORMATS 1
75 #define V4L_COMPFORMATS 2
80 #define V4L_TS_DEFAULT 0
90 #define V4L_TS_MONO2ABS 2
97 #define V4L_TS_CONVERT_READY V4L_TS_DEFAULT
153 #ifdef V4L2_PIX_FMT_H264
156 #ifdef V4L2_PIX_FMT_CPIA1
163 struct v4l2_capability cap;
192 fd, cap.capabilities);
194 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
201 if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
203 "The device does not support the streaming I/O method.\n");
221 struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
222 struct v4l2_pix_format *pix = &fmt.fmt.pix;
229 pix->field = V4L2_FIELD_ANY;
233 if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
235 "The V4L2 driver changed the video from %dx%d to %dx%d\n",
236 *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height);
237 *width = fmt.fmt.pix.width;
238 *height = fmt.fmt.pix.height;
241 if (pix_fmt != fmt.fmt.pix.pixelformat) {
243 "The V4L2 driver changed the pixel format "
244 "from 0x%08X to 0x%08X\n",
245 pix_fmt, fmt.fmt.pix.pixelformat);
249 if (fmt.fmt.pix.field == V4L2_FIELD_INTERLACED) {
266 if (std & V4L2_STD_NTSC) {
279 fmt_conversion_table[i].codec_id == codec_id) &&
282 return fmt_conversion_table[i].
v4l2_fmt;
294 if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt &&
295 fmt_conversion_table[i].codec_id == codec_id) {
296 return fmt_conversion_table[i].
ff_fmt;
308 if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt) {
309 return fmt_conversion_table[i].
codec_id;
316 #if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
317 static void list_framesizes(
AVFormatContext *ctx,
int fd, uint32_t pixelformat)
319 struct v4l2_frmsizeenum vfse = { .pixel_format = pixelformat };
321 while(!ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &vfse)) {
323 case V4L2_FRMSIZE_TYPE_DISCRETE:
325 vfse.discrete.width, vfse.discrete.height);
327 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
328 case V4L2_FRMSIZE_TYPE_STEPWISE:
330 vfse.stepwise.min_width,
331 vfse.stepwise.max_width,
332 vfse.stepwise.step_width,
333 vfse.stepwise.min_height,
334 vfse.stepwise.max_height,
335 vfse.stepwise.step_height);
344 struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
346 while(!ioctl(fd, VIDIOC_ENUM_FMT, &vfd)) {
352 if (!(vfd.flags & V4L2_FMT_FLAG_COMPRESSED) &&
356 fmt_name ? fmt_name :
"Unsupported",
358 }
else if (vfd.flags & V4L2_FMT_FLAG_COMPRESSED &&
362 codec ? codec->
name :
"Unsupported",
368 #ifdef V4L2_FMT_FLAG_EMULATED
369 if (vfd.flags & V4L2_FMT_FLAG_EMULATED) {
374 #if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
375 list_framesizes(ctx, fd, vfd.pixelformat);
385 struct v4l2_requestbuffers req = {
386 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
388 .memory = V4L2_MEMORY_MMAP
393 if (errno == EINVAL) {
418 for (i = 0; i < req.count; i++) {
419 struct v4l2_buffer buf = {
420 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
422 .memory = V4L2_MEMORY_MMAP
433 "Buffer len [%d] = %d != %d\n",
439 PROT_READ | PROT_WRITE, MAP_SHARED,
440 s->
fd, buf.m.offset);
453 struct v4l2_buffer buf = { 0 };
460 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
461 buf.memory = V4L2_MEMORY_MMAP;
462 buf.index = buf_descriptor->
index;
463 fd = buf_descriptor->
fd;
475 #if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC)
476 static int64_t av_gettime_monotonic(
void)
480 clock_gettime(CLOCK_MONOTONIC, &tv);
481 return (int64_t)tv.tv_sec * 1000000 + tv.tv_nsec / 1000;
492 ts <= now + 1 * AV_TIME_BASE && ts >= now - 10 *
AV_TIME_BASE) {
497 #if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC)
498 now = av_gettime_monotonic();
500 (ts <= now + 1 * AV_TIME_BASE && ts >= now - 10 *
AV_TIME_BASE)) {
523 #if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC)
526 int64_t nowm = av_gettime_monotonic();
538 struct v4l2_buffer buf = {
539 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
540 .memory = V4L2_MEMORY_MMAP
546 while ((res =
v4l2_ioctl(s->
fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
548 if (errno == EAGAIN) {
567 "The v4l2 frame is %d bytes, but %d bytes are expected\n",
575 pkt->
size = buf.bytesused;
576 pkt->
pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
582 if (buf_descriptor ==
NULL) {
591 buf_descriptor->
fd = s->
fd;
592 buf_descriptor->
index = buf.index;
593 pkt->
priv = buf_descriptor;
601 enum v4l2_buf_type type;
604 for (i = 0; i < s->
buffers; i++) {
605 struct v4l2_buffer buf = {
606 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
608 .memory = V4L2_MEMORY_MMAP
620 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
634 enum v4l2_buf_type type;
637 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
642 for (i = 0; i < s->
buffers; i++) {
652 struct v4l2_input input = { 0 };
653 struct v4l2_standard standard = { 0 };
654 struct v4l2_streamparm streamparm = { 0 };
655 struct v4l2_fract *tpf = &streamparm.parm.capture.timeperframe;
659 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
677 if (
v4l2_ioctl(s->
fd, VIDIOC_S_INPUT, &input.index) < 0) {
679 "The V4L2 driver ioctl set input(%d) failed\n",
700 "The V4L2 driver set standard: %s, id: %"PRIu64
"\n",
701 s->
standard, (uint64_t)standard.id);
702 if (
v4l2_ioctl(s->
fd, VIDIOC_S_STD, &standard.id) < 0) {
704 "The V4L2 driver ioctl set standard(%s) failed\n",
710 if (framerate_q.
num && framerate_q.
den) {
712 framerate_q.
den, framerate_q.
num);
713 tpf->numerator = framerate_q.
den;
714 tpf->denominator = framerate_q.
num;
716 if (
v4l2_ioctl(s->
fd, VIDIOC_S_PARM, &streamparm) != 0) {
718 "ioctl set time per frame(%d/%d) failed\n",
719 framerate_q.
den, framerate_q.
num);
723 if (framerate_q.
num != tpf->denominator ||
724 framerate_q.
den != tpf->numerator) {
726 "The driver changed the time per frame from "
728 framerate_q.
den, framerate_q.
num,
729 tpf->numerator, tpf->denominator);
732 if (
v4l2_ioctl(s->
fd, VIDIOC_G_PARM, &streamparm) != 0) {
752 if (desired_format == 0 ||
753 device_init(s1, width, height, desired_format) < 0) {
760 desired_format = fmt_conversion_table[i].
v4l2_fmt;
761 if (
device_init(s1, width, height, desired_format) >= 0) {
769 if (desired_format != 0) {
774 return desired_format;
782 uint32_t desired_format;
824 struct v4l2_format fmt;
827 "Querying the device for the current frame size\n");
828 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
836 s->
width = fmt.fmt.pix.width;
837 s->
height = fmt.fmt.pix.height;
839 "Setting frame size to %dx%d\n", s->
width, s->
height);
852 if (desired_format == 0) {
885 if (desired_format == V4L2_PIX_FMT_YVU420)
924 #define OFFSET(x) offsetof(struct video_data, x)
925 #define DEC AV_OPT_FLAG_DECODING_PARAM
954 .
name =
"video4linux2,v4l2",