... | ... |
@@ -187,6 +187,7 @@ External library support: |
187 | 187 |
--enable-libstagefright-h264 enable H.264 decoding via libstagefright [no] |
188 | 188 |
--enable-libtheora enable Theora encoding via libtheora [no] |
189 | 189 |
--enable-libutvideo enable Ut Video decoding via libutvideo [no] |
190 |
+ --enable-libv4l2 enable libv4l2/v4l-utils [no] |
|
190 | 191 |
--enable-libvo-aacenc enable AAC encoding via libvo-aacenc [no] |
191 | 192 |
--enable-libvo-amrwbenc enable AMR-WB encoding via libvo-amrwbenc [no] |
192 | 193 |
--enable-libvorbis enable Vorbis encoding via libvorbis, |
... | ... |
@@ -1022,6 +1023,7 @@ CONFIG_LIST=" |
1022 | 1022 |
libstagefright_h264 |
1023 | 1023 |
libtheora |
1024 | 1024 |
libutvideo |
1025 |
+ libv4l2 |
|
1025 | 1026 |
libvo_aacenc |
1026 | 1027 |
libvo_amrwbenc |
1027 | 1028 |
libvorbis |
... | ... |
@@ -1568,6 +1570,7 @@ jack_indev_deps="jack_jack_h sem_timedwait" |
1568 | 1568 |
lavfi_indev_deps="avfilter" |
1569 | 1569 |
libcdio_indev_deps="libcdio" |
1570 | 1570 |
libdc1394_indev_deps="libdc1394" |
1571 |
+libv4l2_indev_deps="libv4l2" |
|
1571 | 1572 |
openal_indev_deps="openal" |
1572 | 1573 |
oss_indev_deps_any="soundcard_h sys_soundcard_h" |
1573 | 1574 |
oss_outdev_deps_any="soundcard_h sys_soundcard_h" |
... | ... |
@@ -3055,6 +3058,7 @@ enabled libstagefright_h264 && require_cpp libstagefright_h264 "binder/ProcessS |
3055 | 3055 |
media/stagefright/OMXClient.h media/stagefright/OMXCodec.h" android::OMXClient -lstagefright -lmedia -lutils -lbinder |
3056 | 3056 |
enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg |
3057 | 3057 |
enabled libutvideo && require_cpp utvideo "stdint.h stdlib.h utvideo/utvideo.h utvideo/Codec.h" 'CCodec*' -lutvideo -lstdc++ |
3058 |
+enabled libv4l2 && require_pkg_config libv4l2 libv4l2.h v4l2_ioctl |
|
3058 | 3059 |
enabled libvo_aacenc && require libvo_aacenc vo-aacenc/voAAC.h voGetAACEncAPI -lvo-aacenc |
3059 | 3060 |
enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc |
3060 | 3061 |
enabled libvorbis && require libvorbis vorbis/vorbisenc.h vorbis_info_init -lvorbisenc -lvorbis -logg |
... | ... |
@@ -3383,6 +3387,7 @@ echo "libspeex enabled ${libspeex-no}" |
3383 | 3383 |
echo "libstagefright-h264 enabled ${libstagefright_h264-no}" |
3384 | 3384 |
echo "libtheora enabled ${libtheora-no}" |
3385 | 3385 |
echo "libutvideo enabled ${libutvideo-no}" |
3386 |
+echo "libv4l2 enabled ${libv4l2-no}" |
|
3386 | 3387 |
echo "libvo-aacenc support ${libvo_aacenc-no}" |
3387 | 3388 |
echo "libvo-amrwbenc support ${libvo_amrwbenc-no}" |
3388 | 3389 |
echo "libvorbis enabled ${libvorbis-no}" |
... | ... |
@@ -513,6 +513,9 @@ input device will use the frame rate value already set in the driver. |
513 | 513 |
Video4Linux support is deprecated since Linux 2.6.30, and will be |
514 | 514 |
dropped in later versions. |
515 | 515 |
|
516 |
+Note that if FFmpeg is build with v4l-utils support ("--enable-libv4l2" |
|
517 |
+option), it will always be used. |
|
518 |
+ |
|
516 | 519 |
Follow some usage examples of the video4linux devices with the ff* |
517 | 520 |
tools. |
518 | 521 |
@example |
... | ... |
@@ -52,6 +52,18 @@ |
52 | 52 |
#include "libavutil/pixdesc.h" |
53 | 53 |
#include "libavutil/avstring.h" |
54 | 54 |
|
55 |
+#if CONFIG_LIBV4L2 |
|
56 |
+#include <libv4l2.h> |
|
57 |
+#else |
|
58 |
+#define v4l2_open open |
|
59 |
+#define v4l2_close close |
|
60 |
+#define v4l2_dup dup |
|
61 |
+#define v4l2_ioctl ioctl |
|
62 |
+#define v4l2_read read |
|
63 |
+#define v4l2_mmap mmap |
|
64 |
+#define v4l2_munmap munmap |
|
65 |
+#endif |
|
66 |
+ |
|
55 | 67 |
static const int desired_video_buffers = 256; |
56 | 68 |
|
57 | 69 |
enum io_method { |
... | ... |
@@ -113,36 +125,49 @@ static int device_open(AVFormatContext *ctx, uint32_t *capabilities) |
113 | 113 |
{ |
114 | 114 |
struct v4l2_capability cap; |
115 | 115 |
int fd; |
116 |
+#if CONFIG_LIBV4L2 |
|
117 |
+ int fd_libv4l; |
|
118 |
+#endif |
|
116 | 119 |
int res, err; |
117 | 120 |
int flags = O_RDWR; |
118 | 121 |
|
119 | 122 |
if (ctx->flags & AVFMT_FLAG_NONBLOCK) { |
120 | 123 |
flags |= O_NONBLOCK; |
121 | 124 |
} |
122 |
- fd = open(ctx->filename, flags, 0); |
|
125 |
+ fd = v4l2_open(ctx->filename, flags, 0); |
|
123 | 126 |
if (fd < 0) { |
124 | 127 |
av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n", |
125 | 128 |
ctx->filename, strerror(errno)); |
126 | 129 |
return AVERROR(errno); |
127 | 130 |
} |
131 |
+#if CONFIG_LIBV4L2 |
|
132 |
+ fd_libv4l = v4l2_fd_open(fd, 0); |
|
133 |
+ if (fd < 0) { |
|
134 |
+ err = AVERROR(errno); |
|
135 |
+ av_log(ctx, AV_LOG_ERROR, "Cannot open video device with libv4l neither %s : %s\n", |
|
136 |
+ ctx->filename, strerror(errno)); |
|
137 |
+ return err; |
|
138 |
+ } |
|
139 |
+ fd = fd_libv4l; |
|
140 |
+#endif |
|
128 | 141 |
|
129 |
- res = ioctl(fd, VIDIOC_QUERYCAP, &cap); |
|
142 |
+ res = v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap); |
|
130 | 143 |
// ENOIOCTLCMD definition only availble on __KERNEL__ |
131 | 144 |
if (res < 0 && ((err = errno) == 515)) { |
132 | 145 |
av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n"); |
133 |
- close(fd); |
|
146 |
+ v4l2_close(fd); |
|
134 | 147 |
|
135 | 148 |
return AVERROR(515); |
136 | 149 |
} |
137 | 150 |
if (res < 0) { |
138 | 151 |
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", |
139 | 152 |
strerror(errno)); |
140 |
- close(fd); |
|
153 |
+ v4l2_close(fd); |
|
141 | 154 |
return AVERROR(err); |
142 | 155 |
} |
143 | 156 |
if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { |
144 | 157 |
av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n"); |
145 |
- close(fd); |
|
158 |
+ v4l2_close(fd); |
|
146 | 159 |
return AVERROR(ENODEV); |
147 | 160 |
} |
148 | 161 |
*capabilities = cap.capabilities; |
... | ... |
@@ -162,7 +187,7 @@ static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t p |
162 | 162 |
fmt.fmt.pix.height = *height; |
163 | 163 |
fmt.fmt.pix.pixelformat = pix_fmt; |
164 | 164 |
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; |
165 |
- res = ioctl(fd, VIDIOC_S_FMT, &fmt); |
|
165 |
+ res = v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt); |
|
166 | 166 |
if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) { |
167 | 167 |
av_log(ctx, AV_LOG_INFO, "The V4L2 driver changed the video from %dx%d to %dx%d\n", *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height); |
168 | 168 |
*width = fmt.fmt.pix.width; |
... | ... |
@@ -182,7 +207,7 @@ static int first_field(int fd) |
182 | 182 |
int res; |
183 | 183 |
v4l2_std_id std; |
184 | 184 |
|
185 |
- res = ioctl(fd, VIDIOC_G_STD, &std); |
|
185 |
+ res = v4l2_ioctl(fd, VIDIOC_G_STD, &std); |
|
186 | 186 |
if (res < 0) { |
187 | 187 |
return 0; |
188 | 188 |
} |
... | ... |
@@ -245,7 +270,7 @@ static int mmap_init(AVFormatContext *ctx) |
245 | 245 |
req.count = desired_video_buffers; |
246 | 246 |
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
247 | 247 |
req.memory = V4L2_MEMORY_MMAP; |
248 |
- res = ioctl(s->fd, VIDIOC_REQBUFS, &req); |
|
248 |
+ res = v4l2_ioctl(s->fd, VIDIOC_REQBUFS, &req); |
|
249 | 249 |
if (res < 0) { |
250 | 250 |
if (errno == EINVAL) { |
251 | 251 |
av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n"); |
... | ... |
@@ -278,7 +303,7 @@ static int mmap_init(AVFormatContext *ctx) |
278 | 278 |
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
279 | 279 |
buf.memory = V4L2_MEMORY_MMAP; |
280 | 280 |
buf.index = i; |
281 |
- res = ioctl(s->fd, VIDIOC_QUERYBUF, &buf); |
|
281 |
+ res = v4l2_ioctl(s->fd, VIDIOC_QUERYBUF, &buf); |
|
282 | 282 |
if (res < 0) { |
283 | 283 |
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n"); |
284 | 284 |
return AVERROR(errno); |
... | ... |
@@ -290,7 +315,7 @@ static int mmap_init(AVFormatContext *ctx) |
290 | 290 |
|
291 | 291 |
return -1; |
292 | 292 |
} |
293 |
- s->buf_start[i] = mmap (NULL, buf.length, |
|
293 |
+ s->buf_start[i] = v4l2_mmap(NULL, buf.length, |
|
294 | 294 |
PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset); |
295 | 295 |
if (s->buf_start[i] == MAP_FAILED) { |
296 | 296 |
av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno)); |
... | ... |
@@ -322,7 +347,7 @@ static void mmap_release_buffer(AVPacket *pkt) |
322 | 322 |
fd = buf_descriptor->fd; |
323 | 323 |
av_free(buf_descriptor); |
324 | 324 |
|
325 |
- res = ioctl(fd, VIDIOC_QBUF, &buf); |
|
325 |
+ res = v4l2_ioctl(fd, VIDIOC_QBUF, &buf); |
|
326 | 326 |
if (res < 0) { |
327 | 327 |
av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno)); |
328 | 328 |
} |
... | ... |
@@ -341,7 +366,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) |
341 | 341 |
buf.memory = V4L2_MEMORY_MMAP; |
342 | 342 |
|
343 | 343 |
/* FIXME: Some special treatment might be needed in case of loss of signal... */ |
344 |
- while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR)); |
|
344 |
+ while ((res = v4l2_ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR)); |
|
345 | 345 |
if (res < 0) { |
346 | 346 |
if (errno == EAGAIN) { |
347 | 347 |
pkt->size = 0; |
... | ... |
@@ -368,7 +393,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) |
368 | 368 |
* allocate a buffer for memcopying into it |
369 | 369 |
*/ |
370 | 370 |
av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n"); |
371 |
- res = ioctl(s->fd, VIDIOC_QBUF, &buf); |
|
371 |
+ res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf); |
|
372 | 372 |
|
373 | 373 |
return AVERROR(ENOMEM); |
374 | 374 |
} |
... | ... |
@@ -397,7 +422,7 @@ static int mmap_start(AVFormatContext *ctx) |
397 | 397 |
buf.memory = V4L2_MEMORY_MMAP; |
398 | 398 |
buf.index = i; |
399 | 399 |
|
400 |
- res = ioctl(s->fd, VIDIOC_QBUF, &buf); |
|
400 |
+ res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf); |
|
401 | 401 |
if (res < 0) { |
402 | 402 |
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno)); |
403 | 403 |
return AVERROR(errno); |
... | ... |
@@ -405,7 +430,7 @@ static int mmap_start(AVFormatContext *ctx) |
405 | 405 |
} |
406 | 406 |
|
407 | 407 |
type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
408 |
- res = ioctl(s->fd, VIDIOC_STREAMON, &type); |
|
408 |
+ res = v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type); |
|
409 | 409 |
if (res < 0) { |
410 | 410 |
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno)); |
411 | 411 |
return AVERROR(errno); |
... | ... |
@@ -423,9 +448,9 @@ static void mmap_close(struct video_data *s) |
423 | 423 |
/* We do not check for the result, because we could |
424 | 424 |
* not do anything about it anyway... |
425 | 425 |
*/ |
426 |
- ioctl(s->fd, VIDIOC_STREAMOFF, &type); |
|
426 |
+ v4l2_ioctl(s->fd, VIDIOC_STREAMOFF, &type); |
|
427 | 427 |
for (i = 0; i < s->buffers; i++) { |
428 |
- munmap(s->buf_start[i], s->buf_len[i]); |
|
428 |
+ v4l2_munmap(s->buf_start[i], s->buf_len[i]); |
|
429 | 429 |
} |
430 | 430 |
av_free(s->buf_start); |
431 | 431 |
av_free(s->buf_len); |
... | ... |
@@ -450,14 +475,14 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) |
450 | 450 |
|
451 | 451 |
/* set tv video input */ |
452 | 452 |
input.index = s->channel; |
453 |
- if (ioctl(s->fd, VIDIOC_ENUMINPUT, &input) < 0) { |
|
453 |
+ if (v4l2_ioctl(s->fd, VIDIOC_ENUMINPUT, &input) < 0) { |
|
454 | 454 |
av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n"); |
455 | 455 |
return AVERROR(EIO); |
456 | 456 |
} |
457 | 457 |
|
458 | 458 |
av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n", |
459 | 459 |
s->channel, input.name); |
460 |
- if (ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) { |
|
460 |
+ if (v4l2_ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) { |
|
461 | 461 |
av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set input(%d) failed\n", |
462 | 462 |
s->channel); |
463 | 463 |
return AVERROR(EIO); |
... | ... |
@@ -469,7 +494,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) |
469 | 469 |
/* set tv standard */ |
470 | 470 |
for (i = 0;; i++) { |
471 | 471 |
standard.index = i; |
472 |
- ret = ioctl(s->fd, VIDIOC_ENUMSTD, &standard); |
|
472 |
+ ret = v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard); |
|
473 | 473 |
if (ret < 0 || !av_strcasecmp(standard.name, s->standard)) |
474 | 474 |
break; |
475 | 475 |
} |
... | ... |
@@ -480,7 +505,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) |
480 | 480 |
|
481 | 481 |
av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s, id: %"PRIu64"\n", |
482 | 482 |
s->standard, (uint64_t)standard.id); |
483 |
- if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) { |
|
483 |
+ if (v4l2_ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) { |
|
484 | 484 |
av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n", |
485 | 485 |
s->standard); |
486 | 486 |
return AVERROR(EIO); |
... | ... |
@@ -492,7 +517,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) |
492 | 492 |
framerate_q.den, framerate_q.num); |
493 | 493 |
tpf->numerator = framerate_q.den; |
494 | 494 |
tpf->denominator = framerate_q.num; |
495 |
- if (ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) { |
|
495 |
+ if (v4l2_ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) { |
|
496 | 496 |
av_log(s1, AV_LOG_ERROR, |
497 | 497 |
"ioctl set time per frame(%d/%d) failed\n", |
498 | 498 |
framerate_q.den, framerate_q.num); |
... | ... |
@@ -508,7 +533,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) |
508 | 508 |
} |
509 | 509 |
} else { |
510 | 510 |
/* if timebase value is not set, read the timebase value from the driver */ |
511 |
- if (ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) { |
|
511 |
+ if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) { |
|
512 | 512 |
av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", strerror(errno)); |
513 | 513 |
return AVERROR(errno); |
514 | 514 |
} |
... | ... |
@@ -590,7 +615,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
590 | 590 |
|
591 | 591 |
av_log(s1, AV_LOG_VERBOSE, "Querying the device for the current frame size\n"); |
592 | 592 |
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
593 |
- if (ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) { |
|
593 |
+ if (v4l2_ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) { |
|
594 | 594 |
av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", strerror(errno)); |
595 | 595 |
res = AVERROR(errno); |
596 | 596 |
goto out; |
... | ... |
@@ -604,7 +629,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
604 | 604 |
if (desired_format == 0) { |
605 | 605 |
av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for " |
606 | 606 |
"codec_id %d, pix_fmt %d.\n", s1->video_codec_id, pix_fmt); |
607 |
- close(s->fd); |
|
607 |
+ v4l2_close(s->fd); |
|
608 | 608 |
|
609 | 609 |
res = AVERROR(EIO); |
610 | 610 |
goto out; |
... | ... |
@@ -629,7 +654,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
629 | 629 |
res = read_init(s1); |
630 | 630 |
} |
631 | 631 |
if (res < 0) { |
632 |
- close(s->fd); |
|
632 |
+ v4l2_close(s->fd); |
|
633 | 633 |
res = AVERROR(EIO); |
634 | 634 |
goto out; |
635 | 635 |
} |
... | ... |
@@ -681,7 +706,7 @@ static int v4l2_read_close(AVFormatContext *s1) |
681 | 681 |
mmap_close(s); |
682 | 682 |
} |
683 | 683 |
|
684 |
- close(s->fd); |
|
684 |
+ v4l2_close(s->fd); |
|
685 | 685 |
return 0; |
686 | 686 |
} |
687 | 687 |
|