00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #undef __STRICT_ANSI__ //workaround due to broken kernel headers
00031 #include "config.h"
00032 #include "libavformat/avformat.h"
00033 #include "libavformat/internal.h"
00034 #include <unistd.h>
00035 #include <fcntl.h>
00036 #include <sys/ioctl.h>
00037 #include <sys/mman.h>
00038 #include <sys/time.h>
00039 #include <poll.h>
00040 #if HAVE_SYS_VIDEOIO_H
00041 #include <sys/videoio.h>
00042 #else
00043 #include <linux/videodev2.h>
00044 #endif
00045 #include <time.h>
00046 #include "libavutil/imgutils.h"
00047 #include "libavutil/log.h"
00048 #include "libavutil/opt.h"
00049 #include "libavutil/parseutils.h"
00050 #include "libavutil/pixdesc.h"
00051 #include "libavutil/avstring.h"
00052 #include "libavutil/mathematics.h"
00053
00054 static const int desired_video_buffers = 256;
00055
00056 #define V4L_ALLFORMATS 3
00057 #define V4L_RAWFORMATS 1
00058 #define V4L_COMPFORMATS 2
00059
00060 struct video_data {
00061 AVClass *class;
00062 int fd;
00063 int frame_format;
00064 int width, height;
00065 int frame_size;
00066 int timeout;
00067 int interlaced;
00068 int top_field_first;
00069
00070 int buffers;
00071 void **buf_start;
00072 unsigned int *buf_len;
00073 char *standard;
00074 int channel;
00075 char *video_size;
00077 char *pixel_format;
00078 int list_format;
00079 char *framerate;
00080 };
00081
00082 struct buff_data {
00083 int index;
00084 int fd;
00085 };
00086
00087 struct fmt_map {
00088 enum PixelFormat ff_fmt;
00089 enum CodecID codec_id;
00090 uint32_t v4l2_fmt;
00091 };
00092
00093 static struct fmt_map fmt_conversion_table[] = {
00094
00095 { PIX_FMT_YUV420P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV420 },
00096 { PIX_FMT_YUV422P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV422P },
00097 { PIX_FMT_YUYV422, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUYV },
00098 { PIX_FMT_UYVY422, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_UYVY },
00099 { PIX_FMT_YUV411P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV411P },
00100 { PIX_FMT_YUV410P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV410 },
00101 { PIX_FMT_RGB555, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB555 },
00102 { PIX_FMT_RGB565, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB565 },
00103 { PIX_FMT_BGR24, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_BGR24 },
00104 { PIX_FMT_RGB24, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB24 },
00105 { PIX_FMT_BGRA, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_BGR32 },
00106 { PIX_FMT_GRAY8, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_GREY },
00107 { PIX_FMT_NV12, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV12 },
00108 { PIX_FMT_NONE, CODEC_ID_MJPEG, V4L2_PIX_FMT_MJPEG },
00109 { PIX_FMT_NONE, CODEC_ID_MJPEG, V4L2_PIX_FMT_JPEG },
00110 };
00111
00112 static int device_open(AVFormatContext *ctx)
00113 {
00114 struct v4l2_capability cap;
00115 int fd;
00116 int res, err;
00117 int flags = O_RDWR;
00118
00119 if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
00120 flags |= O_NONBLOCK;
00121 }
00122
00123 fd = open(ctx->filename, flags, 0);
00124 if (fd < 0) {
00125 err = errno;
00126
00127 av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
00128 ctx->filename, strerror(err));
00129
00130 return AVERROR(err);
00131 }
00132
00133 res = ioctl(fd, VIDIOC_QUERYCAP, &cap);
00134 if (res < 0) {
00135 err = errno;
00136 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
00137 strerror(err));
00138
00139 goto fail;
00140 }
00141
00142 av_log(ctx, AV_LOG_VERBOSE, "[%d]Capabilities: %x\n",
00143 fd, cap.capabilities);
00144
00145 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
00146 av_log(ctx, AV_LOG_ERROR, "Not a video capture device.\n");
00147 err = ENODEV;
00148
00149 goto fail;
00150 }
00151
00152 if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
00153 av_log(ctx, AV_LOG_ERROR,
00154 "The device does not support the streaming I/O method.\n");
00155 err = ENOSYS;
00156
00157 goto fail;
00158 }
00159
00160 return fd;
00161
00162 fail:
00163 close(fd);
00164 return AVERROR(err);
00165 }
00166
00167 static int device_init(AVFormatContext *ctx, int *width, int *height,
00168 uint32_t pix_fmt)
00169 {
00170 struct video_data *s = ctx->priv_data;
00171 int fd = s->fd;
00172 struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
00173 struct v4l2_pix_format *pix = &fmt.fmt.pix;
00174
00175 int res;
00176
00177 pix->width = *width;
00178 pix->height = *height;
00179 pix->pixelformat = pix_fmt;
00180 pix->field = V4L2_FIELD_ANY;
00181
00182 res = ioctl(fd, VIDIOC_S_FMT, &fmt);
00183
00184 if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
00185 av_log(ctx, AV_LOG_INFO,
00186 "The V4L2 driver changed the video from %dx%d to %dx%d\n",
00187 *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height);
00188 *width = fmt.fmt.pix.width;
00189 *height = fmt.fmt.pix.height;
00190 }
00191
00192 if (pix_fmt != fmt.fmt.pix.pixelformat) {
00193 av_log(ctx, AV_LOG_DEBUG,
00194 "The V4L2 driver changed the pixel format "
00195 "from 0x%08X to 0x%08X\n",
00196 pix_fmt, fmt.fmt.pix.pixelformat);
00197 res = -1;
00198 }
00199
00200 if (fmt.fmt.pix.field == V4L2_FIELD_INTERLACED) {
00201 av_log(ctx, AV_LOG_DEBUG, "The V4L2 driver using the interlaced mode");
00202 s->interlaced = 1;
00203 }
00204
00205 return res;
00206 }
00207
00208 static int first_field(int fd)
00209 {
00210 int res;
00211 v4l2_std_id std;
00212
00213 res = ioctl(fd, VIDIOC_G_STD, &std);
00214 if (res < 0) {
00215 return 0;
00216 }
00217 if (std & V4L2_STD_NTSC) {
00218 return 0;
00219 }
00220
00221 return 1;
00222 }
00223
00224 static uint32_t fmt_ff2v4l(enum PixelFormat pix_fmt, enum CodecID codec_id)
00225 {
00226 int i;
00227
00228 for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00229 if ((codec_id == CODEC_ID_NONE ||
00230 fmt_conversion_table[i].codec_id == codec_id) &&
00231 (pix_fmt == PIX_FMT_NONE ||
00232 fmt_conversion_table[i].ff_fmt == pix_fmt)) {
00233 return fmt_conversion_table[i].v4l2_fmt;
00234 }
00235 }
00236
00237 return 0;
00238 }
00239
00240 static enum PixelFormat fmt_v4l2ff(uint32_t v4l2_fmt, enum CodecID codec_id)
00241 {
00242 int i;
00243
00244 for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00245 if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt &&
00246 fmt_conversion_table[i].codec_id == codec_id) {
00247 return fmt_conversion_table[i].ff_fmt;
00248 }
00249 }
00250
00251 return PIX_FMT_NONE;
00252 }
00253
00254 static enum CodecID fmt_v4l2codec(uint32_t v4l2_fmt)
00255 {
00256 int i;
00257
00258 for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00259 if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt) {
00260 return fmt_conversion_table[i].codec_id;
00261 }
00262 }
00263
00264 return CODEC_ID_NONE;
00265 }
00266
00267 #if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
00268 static void list_framesizes(AVFormatContext *ctx, int fd, uint32_t pixelformat)
00269 {
00270 struct v4l2_frmsizeenum vfse = { .pixel_format = pixelformat };
00271
00272 while(!ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &vfse)) {
00273 switch (vfse.type) {
00274 case V4L2_FRMSIZE_TYPE_DISCRETE:
00275 av_log(ctx, AV_LOG_INFO, " %ux%u",
00276 vfse.discrete.width, vfse.discrete.height);
00277 break;
00278 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
00279 case V4L2_FRMSIZE_TYPE_STEPWISE:
00280 av_log(ctx, AV_LOG_INFO, " {%u-%u, %u}x{%u-%u, %u}",
00281 vfse.stepwise.min_width,
00282 vfse.stepwise.max_width,
00283 vfse.stepwise.step_width,
00284 vfse.stepwise.min_height,
00285 vfse.stepwise.max_height,
00286 vfse.stepwise.step_height);
00287 }
00288 vfse.index++;
00289 }
00290 }
00291 #endif
00292
00293 static void list_formats(AVFormatContext *ctx, int fd, int type)
00294 {
00295 struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
00296
00297 while(!ioctl(fd, VIDIOC_ENUM_FMT, &vfd)) {
00298 enum CodecID codec_id = fmt_v4l2codec(vfd.pixelformat);
00299 enum PixelFormat pix_fmt = fmt_v4l2ff(vfd.pixelformat, codec_id);
00300
00301 vfd.index++;
00302
00303 if (!(vfd.flags & V4L2_FMT_FLAG_COMPRESSED) &&
00304 type & V4L_RAWFORMATS) {
00305 const char *fmt_name = av_get_pix_fmt_name(pix_fmt);
00306 av_log(ctx, AV_LOG_INFO, "R : %9s : %20s :",
00307 fmt_name ? fmt_name : "Unsupported",
00308 vfd.description);
00309 } else if (vfd.flags & V4L2_FMT_FLAG_COMPRESSED &&
00310 type & V4L_COMPFORMATS) {
00311 AVCodec *codec = avcodec_find_encoder(codec_id);
00312 av_log(ctx, AV_LOG_INFO, "C : %9s : %20s :",
00313 codec ? codec->name : "Unsupported",
00314 vfd.description);
00315 } else {
00316 continue;
00317 }
00318
00319 #ifdef V4L2_FMT_FLAG_EMULATED
00320 if (vfd.flags & V4L2_FMT_FLAG_EMULATED) {
00321 av_log(ctx, AV_LOG_WARNING, "%s", "Emulated");
00322 continue;
00323 }
00324 #endif
00325 #if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
00326 list_framesizes(ctx, fd, vfd.pixelformat);
00327 #endif
00328 av_log(ctx, AV_LOG_INFO, "\n");
00329 }
00330 }
00331
00332 static int mmap_init(AVFormatContext *ctx)
00333 {
00334 int i, res;
00335 struct video_data *s = ctx->priv_data;
00336 struct v4l2_requestbuffers req = {
00337 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
00338 .count = desired_video_buffers,
00339 .memory = V4L2_MEMORY_MMAP
00340 };
00341
00342 res = ioctl(s->fd, VIDIOC_REQBUFS, &req);
00343 if (res < 0) {
00344 if (errno == EINVAL) {
00345 av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");
00346 } else {
00347 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
00348 }
00349
00350 return AVERROR(errno);
00351 }
00352
00353 if (req.count < 2) {
00354 av_log(ctx, AV_LOG_ERROR, "Insufficient buffer memory\n");
00355
00356 return AVERROR(ENOMEM);
00357 }
00358 s->buffers = req.count;
00359 s->buf_start = av_malloc(sizeof(void *) * s->buffers);
00360 if (s->buf_start == NULL) {
00361 av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
00362
00363 return AVERROR(ENOMEM);
00364 }
00365 s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers);
00366 if (s->buf_len == NULL) {
00367 av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
00368 av_free(s->buf_start);
00369
00370 return AVERROR(ENOMEM);
00371 }
00372
00373 for (i = 0; i < req.count; i++) {
00374 struct v4l2_buffer buf = {
00375 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
00376 .index = i,
00377 .memory = V4L2_MEMORY_MMAP
00378 };
00379
00380 res = ioctl(s->fd, VIDIOC_QUERYBUF, &buf);
00381 if (res < 0) {
00382 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
00383
00384 return AVERROR(errno);
00385 }
00386
00387 s->buf_len[i] = buf.length;
00388 if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) {
00389 av_log(ctx, AV_LOG_ERROR,
00390 "Buffer len [%d] = %d != %d\n",
00391 i, s->buf_len[i], s->frame_size);
00392
00393 return -1;
00394 }
00395 s->buf_start[i] = mmap(NULL, buf.length,
00396 PROT_READ | PROT_WRITE, MAP_SHARED,
00397 s->fd, buf.m.offset);
00398
00399 if (s->buf_start[i] == MAP_FAILED) {
00400 av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
00401
00402 return AVERROR(errno);
00403 }
00404 }
00405
00406 return 0;
00407 }
00408
00409 static void mmap_release_buffer(AVPacket *pkt)
00410 {
00411 struct v4l2_buffer buf = { 0 };
00412 int res, fd;
00413 struct buff_data *buf_descriptor = pkt->priv;
00414
00415 if (pkt->data == NULL)
00416 return;
00417
00418 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00419 buf.memory = V4L2_MEMORY_MMAP;
00420 buf.index = buf_descriptor->index;
00421 fd = buf_descriptor->fd;
00422 av_free(buf_descriptor);
00423
00424 res = ioctl(fd, VIDIOC_QBUF, &buf);
00425 if (res < 0)
00426 av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
00427 strerror(errno));
00428
00429 pkt->data = NULL;
00430 pkt->size = 0;
00431 }
00432
00433 static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
00434 {
00435 struct video_data *s = ctx->priv_data;
00436 struct v4l2_buffer buf = {
00437 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
00438 .memory = V4L2_MEMORY_MMAP
00439 };
00440 struct buff_data *buf_descriptor;
00441 struct pollfd p = { .fd = s->fd, .events = POLLIN };
00442 int res;
00443
00444 res = poll(&p, 1, s->timeout);
00445 if (res < 0)
00446 return AVERROR(errno);
00447
00448 if (!(p.revents & (POLLIN | POLLERR | POLLHUP)))
00449 return AVERROR(EAGAIN);
00450
00451
00452 while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
00453 if (res < 0) {
00454 if (errno == EAGAIN) {
00455 pkt->size = 0;
00456
00457 return AVERROR(EAGAIN);
00458 }
00459 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n",
00460 strerror(errno));
00461
00462 return AVERROR(errno);
00463 }
00464 assert (buf.index < s->buffers);
00465 if (s->frame_size > 0 && buf.bytesused != s->frame_size) {
00466 av_log(ctx, AV_LOG_ERROR,
00467 "The v4l2 frame is %d bytes, but %d bytes are expected\n",
00468 buf.bytesused, s->frame_size);
00469
00470 return AVERROR_INVALIDDATA;
00471 }
00472
00473
00474 pkt->data= s->buf_start[buf.index];
00475 pkt->size = buf.bytesused;
00476 pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
00477 pkt->destruct = mmap_release_buffer;
00478 buf_descriptor = av_malloc(sizeof(struct buff_data));
00479 if (buf_descriptor == NULL) {
00480
00481
00482
00483 av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
00484 res = ioctl(s->fd, VIDIOC_QBUF, &buf);
00485
00486 return AVERROR(ENOMEM);
00487 }
00488 buf_descriptor->fd = s->fd;
00489 buf_descriptor->index = buf.index;
00490 pkt->priv = buf_descriptor;
00491
00492 return s->buf_len[buf.index];
00493 }
00494
00495 static int mmap_start(AVFormatContext *ctx)
00496 {
00497 struct video_data *s = ctx->priv_data;
00498 enum v4l2_buf_type type;
00499 int i, res;
00500
00501 for (i = 0; i < s->buffers; i++) {
00502 struct v4l2_buffer buf = {
00503 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
00504 .index = i,
00505 .memory = V4L2_MEMORY_MMAP
00506 };
00507
00508 res = ioctl(s->fd, VIDIOC_QBUF, &buf);
00509 if (res < 0) {
00510 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
00511 strerror(errno));
00512
00513 return AVERROR(errno);
00514 }
00515 }
00516
00517 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00518 res = ioctl(s->fd, VIDIOC_STREAMON, &type);
00519 if (res < 0) {
00520 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n",
00521 strerror(errno));
00522
00523 return AVERROR(errno);
00524 }
00525
00526 return 0;
00527 }
00528
00529 static void mmap_close(struct video_data *s)
00530 {
00531 enum v4l2_buf_type type;
00532 int i;
00533
00534 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00535
00536
00537
00538 ioctl(s->fd, VIDIOC_STREAMOFF, &type);
00539 for (i = 0; i < s->buffers; i++) {
00540 munmap(s->buf_start[i], s->buf_len[i]);
00541 }
00542 av_free(s->buf_start);
00543 av_free(s->buf_len);
00544 }
00545
00546 static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
00547 {
00548 struct video_data *s = s1->priv_data;
00549 struct v4l2_input input = { 0 };
00550 struct v4l2_standard standard = { 0 };
00551 struct v4l2_streamparm streamparm = { 0 };
00552 struct v4l2_fract *tpf = &streamparm.parm.capture.timeperframe;
00553 AVRational framerate_q = { 0 };
00554 int i, ret;
00555
00556 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00557
00558 if (s->framerate &&
00559 (ret = av_parse_video_rate(&framerate_q, s->framerate)) < 0) {
00560 av_log(s1, AV_LOG_ERROR, "Could not parse framerate '%s'.\n",
00561 s->framerate);
00562 return ret;
00563 }
00564
00565
00566 input.index = s->channel;
00567 if (ioctl(s->fd, VIDIOC_ENUMINPUT, &input) < 0) {
00568 av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n");
00569 return AVERROR(EIO);
00570 }
00571
00572 av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n",
00573 s->channel, input.name);
00574 if (ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) {
00575 av_log(s1, AV_LOG_ERROR,
00576 "The V4L2 driver ioctl set input(%d) failed\n",
00577 s->channel);
00578 return AVERROR(EIO);
00579 }
00580
00581 if (s->standard) {
00582 av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
00583 s->standard);
00584
00585 for(i=0;;i++) {
00586 standard.index = i;
00587 if (ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) {
00588 av_log(s1, AV_LOG_ERROR,
00589 "The V4L2 driver ioctl set standard(%s) failed\n",
00590 s->standard);
00591 return AVERROR(EIO);
00592 }
00593
00594 if (!av_strcasecmp(standard.name, s->standard)) {
00595 break;
00596 }
00597 }
00598
00599 av_log(s1, AV_LOG_DEBUG,
00600 "The V4L2 driver set standard: %s, id: %"PRIu64"\n",
00601 s->standard, (uint64_t)standard.id);
00602 if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
00603 av_log(s1, AV_LOG_ERROR,
00604 "The V4L2 driver ioctl set standard(%s) failed\n",
00605 s->standard);
00606 return AVERROR(EIO);
00607 }
00608 }
00609
00610 if (framerate_q.num && framerate_q.den) {
00611 av_log(s1, AV_LOG_DEBUG, "Setting time per frame to %d/%d\n",
00612 framerate_q.den, framerate_q.num);
00613 tpf->numerator = framerate_q.den;
00614 tpf->denominator = framerate_q.num;
00615
00616 if (ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) {
00617 av_log(s1, AV_LOG_ERROR,
00618 "ioctl set time per frame(%d/%d) failed\n",
00619 framerate_q.den, framerate_q.num);
00620 return AVERROR(EIO);
00621 }
00622
00623 if (framerate_q.num != tpf->denominator ||
00624 framerate_q.den != tpf->numerator) {
00625 av_log(s1, AV_LOG_INFO,
00626 "The driver changed the time per frame from "
00627 "%d/%d to %d/%d\n",
00628 framerate_q.den, framerate_q.num,
00629 tpf->numerator, tpf->denominator);
00630 }
00631 } else {
00632 if (ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) {
00633 av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n",
00634 strerror(errno));
00635 return AVERROR(errno);
00636 }
00637 }
00638 s1->streams[0]->codec->time_base.den = tpf->denominator;
00639 s1->streams[0]->codec->time_base.num = tpf->numerator;
00640
00641 s->timeout = 100 +
00642 av_rescale_q(1, s1->streams[0]->codec->time_base,
00643 (AVRational){1, 1000});
00644
00645 return 0;
00646 }
00647
00648 static uint32_t device_try_init(AVFormatContext *s1,
00649 enum PixelFormat pix_fmt,
00650 int *width,
00651 int *height,
00652 enum CodecID *codec_id)
00653 {
00654 uint32_t desired_format = fmt_ff2v4l(pix_fmt, s1->video_codec_id);
00655
00656 if (desired_format == 0 ||
00657 device_init(s1, width, height, desired_format) < 0) {
00658 int i;
00659
00660 desired_format = 0;
00661 for (i = 0; i<FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00662 if (s1->video_codec_id == CODEC_ID_NONE ||
00663 fmt_conversion_table[i].codec_id == s1->video_codec_id) {
00664 desired_format = fmt_conversion_table[i].v4l2_fmt;
00665 if (device_init(s1, width, height, desired_format) >= 0) {
00666 break;
00667 }
00668 desired_format = 0;
00669 }
00670 }
00671 }
00672
00673 if (desired_format != 0) {
00674 *codec_id = fmt_v4l2codec(desired_format);
00675 assert(*codec_id != CODEC_ID_NONE);
00676 }
00677
00678 return desired_format;
00679 }
00680
00681 static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
00682 {
00683 struct video_data *s = s1->priv_data;
00684 AVStream *st;
00685 int res = 0;
00686 uint32_t desired_format;
00687 enum CodecID codec_id;
00688 enum PixelFormat pix_fmt = PIX_FMT_NONE;
00689
00690 st = avformat_new_stream(s1, NULL);
00691 if (!st) {
00692 res = AVERROR(ENOMEM);
00693 goto out;
00694 }
00695
00696 s->fd = device_open(s1);
00697 if (s->fd < 0) {
00698 res = s->fd;
00699 goto out;
00700 }
00701
00702 if (s->list_format) {
00703 list_formats(s1, s->fd, s->list_format);
00704 res = AVERROR_EXIT;
00705 goto out;
00706 }
00707
00708 avpriv_set_pts_info(st, 64, 1, 1000000);
00709
00710 if (s->video_size &&
00711 (res = av_parse_video_size(&s->width, &s->height, s->video_size)) < 0) {
00712 av_log(s1, AV_LOG_ERROR, "Could not parse video size '%s'.\n",
00713 s->video_size);
00714 goto out;
00715 }
00716
00717 if (s->pixel_format) {
00718 AVCodec *codec = avcodec_find_decoder_by_name(s->pixel_format);
00719
00720 if (codec)
00721 s1->video_codec_id = codec->id;
00722
00723 pix_fmt = av_get_pix_fmt(s->pixel_format);
00724
00725 if (pix_fmt == PIX_FMT_NONE && !codec) {
00726 av_log(s1, AV_LOG_ERROR, "No such input format: %s.\n",
00727 s->pixel_format);
00728
00729 res = AVERROR(EINVAL);
00730 goto out;
00731 }
00732 }
00733
00734 if (!s->width && !s->height) {
00735 struct v4l2_format fmt;
00736
00737 av_log(s1, AV_LOG_VERBOSE,
00738 "Querying the device for the current frame size\n");
00739 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00740 if (ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) {
00741 av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n",
00742 strerror(errno));
00743 res = AVERROR(errno);
00744 goto out;
00745 }
00746
00747 s->width = fmt.fmt.pix.width;
00748 s->height = fmt.fmt.pix.height;
00749 av_log(s1, AV_LOG_VERBOSE,
00750 "Setting frame size to %dx%d\n", s->width, s->height);
00751 }
00752
00753 desired_format = device_try_init(s1, pix_fmt, &s->width, &s->height,
00754 &codec_id);
00755 if (desired_format == 0) {
00756 av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
00757 "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, pix_fmt);
00758 close(s->fd);
00759
00760 res = AVERROR(EIO);
00761 goto out;
00762 }
00763
00764 if ((res = av_image_check_size(s->width, s->height, 0, s1) < 0))
00765 goto out;
00766
00767 s->frame_format = desired_format;
00768
00769 if ((res = v4l2_set_parameters(s1, ap) < 0))
00770 goto out;
00771
00772 st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id);
00773 s->frame_size =
00774 avpicture_get_size(st->codec->pix_fmt, s->width, s->height);
00775
00776 if ((res = mmap_init(s1)) ||
00777 (res = mmap_start(s1)) < 0) {
00778 close(s->fd);
00779 goto out;
00780 }
00781
00782 s->top_field_first = first_field(s->fd);
00783
00784 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00785 st->codec->codec_id = codec_id;
00786 if (codec_id == CODEC_ID_RAWVIDEO)
00787 st->codec->codec_tag =
00788 avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
00789 st->codec->width = s->width;
00790 st->codec->height = s->height;
00791 st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;
00792
00793 out:
00794 return res;
00795 }
00796
00797 static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt)
00798 {
00799 struct video_data *s = s1->priv_data;
00800 AVFrame *frame = s1->streams[0]->codec->coded_frame;
00801 int res;
00802
00803 av_init_packet(pkt);
00804 if ((res = mmap_read_frame(s1, pkt)) < 0) {
00805 return res;
00806 }
00807
00808 if (frame && s->interlaced) {
00809 frame->interlaced_frame = 1;
00810 frame->top_field_first = s->top_field_first;
00811 }
00812
00813 return pkt->size;
00814 }
00815
00816 static int v4l2_read_close(AVFormatContext *s1)
00817 {
00818 struct video_data *s = s1->priv_data;
00819
00820 mmap_close(s);
00821
00822 close(s->fd);
00823 return 0;
00824 }
00825
00826 #define OFFSET(x) offsetof(struct video_data, x)
00827 #define DEC AV_OPT_FLAG_DECODING_PARAM
00828 static const AVOption options[] = {
00829 { "standard", "TV standard, used only by analog frame grabber", OFFSET(standard), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC },
00830 { "channel", "TV channel, used only by frame grabber", OFFSET(channel), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC },
00831 { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
00832 { "pixel_format", "Preferred pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
00833 { "input_format", "Preferred pixel format (for raw video) or codec name", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
00834 { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
00835 { "list_formats", "List available formats and exit", OFFSET(list_format), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC, "list_formats" },
00836 { "all", "Show all available formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_ALLFORMATS }, 0, INT_MAX, DEC, "list_formats" },
00837 { "raw", "Show only non-compressed formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_RAWFORMATS }, 0, INT_MAX, DEC, "list_formats" },
00838 { "compressed", "Show only compressed formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_COMPFORMATS }, 0, INT_MAX, DEC, "list_formats" },
00839 { NULL },
00840 };
00841
00842 static const AVClass v4l2_class = {
00843 .class_name = "V4L2 indev",
00844 .item_name = av_default_item_name,
00845 .option = options,
00846 .version = LIBAVUTIL_VERSION_INT,
00847 };
00848
00849 AVInputFormat ff_v4l2_demuxer = {
00850 .name = "video4linux2",
00851 .long_name = NULL_IF_CONFIG_SMALL("Video4Linux2 device grab"),
00852 .priv_data_size = sizeof(struct video_data),
00853 .read_header = v4l2_read_header,
00854 .read_packet = v4l2_read_packet,
00855 .read_close = v4l2_read_close,
00856 .flags = AVFMT_NOFILE,
00857 .priv_class = &v4l2_class,
00858 };