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 <unistd.h>
00034 #include <fcntl.h>
00035 #include <sys/ioctl.h>
00036 #include <sys/mman.h>
00037 #include <sys/time.h>
00038 #if HAVE_SYS_VIDEOIO_H
00039 #include <sys/videoio.h>
00040 #else
00041 #include <asm/types.h>
00042 #include <linux/videodev2.h>
00043 #endif
00044 #include <time.h>
00045 #include <strings.h>
00046
00047 static const int desired_video_buffers = 256;
00048
00049 enum io_method {
00050 io_read,
00051 io_mmap,
00052 io_userptr
00053 };
00054
00055 struct video_data {
00056 int fd;
00057 int frame_format;
00058 enum io_method io_method;
00059 int width, height;
00060 int frame_size;
00061 int top_field_first;
00062
00063 int buffers;
00064 void **buf_start;
00065 unsigned int *buf_len;
00066 };
00067
00068 struct buff_data {
00069 int index;
00070 int fd;
00071 };
00072
00073 struct fmt_map {
00074 enum PixelFormat ff_fmt;
00075 enum CodecID codec_id;
00076 uint32_t v4l2_fmt;
00077 };
00078
00079 static struct fmt_map fmt_conversion_table[] = {
00080 {
00081 .ff_fmt = PIX_FMT_YUV420P,
00082 .codec_id = CODEC_ID_RAWVIDEO,
00083 .v4l2_fmt = V4L2_PIX_FMT_YUV420,
00084 },
00085 {
00086 .ff_fmt = PIX_FMT_YUV422P,
00087 .codec_id = CODEC_ID_RAWVIDEO,
00088 .v4l2_fmt = V4L2_PIX_FMT_YUV422P,
00089 },
00090 {
00091 .ff_fmt = PIX_FMT_YUYV422,
00092 .codec_id = CODEC_ID_RAWVIDEO,
00093 .v4l2_fmt = V4L2_PIX_FMT_YUYV,
00094 },
00095 {
00096 .ff_fmt = PIX_FMT_UYVY422,
00097 .codec_id = CODEC_ID_RAWVIDEO,
00098 .v4l2_fmt = V4L2_PIX_FMT_UYVY,
00099 },
00100 {
00101 .ff_fmt = PIX_FMT_YUV411P,
00102 .codec_id = CODEC_ID_RAWVIDEO,
00103 .v4l2_fmt = V4L2_PIX_FMT_YUV411P,
00104 },
00105 {
00106 .ff_fmt = PIX_FMT_YUV410P,
00107 .codec_id = CODEC_ID_RAWVIDEO,
00108 .v4l2_fmt = V4L2_PIX_FMT_YUV410,
00109 },
00110 {
00111 .ff_fmt = PIX_FMT_RGB555,
00112 .codec_id = CODEC_ID_RAWVIDEO,
00113 .v4l2_fmt = V4L2_PIX_FMT_RGB555,
00114 },
00115 {
00116 .ff_fmt = PIX_FMT_RGB565,
00117 .codec_id = CODEC_ID_RAWVIDEO,
00118 .v4l2_fmt = V4L2_PIX_FMT_RGB565,
00119 },
00120 {
00121 .ff_fmt = PIX_FMT_BGR24,
00122 .codec_id = CODEC_ID_RAWVIDEO,
00123 .v4l2_fmt = V4L2_PIX_FMT_BGR24,
00124 },
00125 {
00126 .ff_fmt = PIX_FMT_RGB24,
00127 .codec_id = CODEC_ID_RAWVIDEO,
00128 .v4l2_fmt = V4L2_PIX_FMT_RGB24,
00129 },
00130 {
00131 .ff_fmt = PIX_FMT_BGRA,
00132 .codec_id = CODEC_ID_RAWVIDEO,
00133 .v4l2_fmt = V4L2_PIX_FMT_BGR32,
00134 },
00135 {
00136 .ff_fmt = PIX_FMT_GRAY8,
00137 .codec_id = CODEC_ID_RAWVIDEO,
00138 .v4l2_fmt = V4L2_PIX_FMT_GREY,
00139 },
00140 {
00141 .ff_fmt = PIX_FMT_NONE,
00142 .codec_id = CODEC_ID_MJPEG,
00143 .v4l2_fmt = V4L2_PIX_FMT_MJPEG,
00144 },
00145 {
00146 .ff_fmt = PIX_FMT_NONE,
00147 .codec_id = CODEC_ID_MJPEG,
00148 .v4l2_fmt = V4L2_PIX_FMT_JPEG,
00149 },
00150 };
00151
00152 static int device_open(AVFormatContext *ctx, uint32_t *capabilities)
00153 {
00154 struct v4l2_capability cap;
00155 int fd;
00156 int res;
00157 int flags = O_RDWR;
00158
00159 if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
00160 flags |= O_NONBLOCK;
00161 }
00162 fd = open(ctx->filename, flags, 0);
00163 if (fd < 0) {
00164 av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
00165 ctx->filename, strerror(errno));
00166
00167 return -1;
00168 }
00169
00170 res = ioctl(fd, VIDIOC_QUERYCAP, &cap);
00171
00172 if (res < 0 && errno == 515)
00173 {
00174 av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n");
00175 close(fd);
00176
00177 return -1;
00178 }
00179 if (res < 0) {
00180 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
00181 strerror(errno));
00182 close(fd);
00183
00184 return -1;
00185 }
00186 if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
00187 av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n");
00188 close(fd);
00189
00190 return -1;
00191 }
00192 *capabilities = cap.capabilities;
00193
00194 return fd;
00195 }
00196
00197 static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pix_fmt)
00198 {
00199 struct video_data *s = ctx->priv_data;
00200 int fd = s->fd;
00201 struct v4l2_format fmt;
00202 int res;
00203
00204 memset(&fmt, 0, sizeof(struct v4l2_format));
00205 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00206 fmt.fmt.pix.width = *width;
00207 fmt.fmt.pix.height = *height;
00208 fmt.fmt.pix.pixelformat = pix_fmt;
00209 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
00210 res = ioctl(fd, VIDIOC_S_FMT, &fmt);
00211 if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
00212 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);
00213 *width = fmt.fmt.pix.width;
00214 *height = fmt.fmt.pix.height;
00215 }
00216
00217 if (pix_fmt != fmt.fmt.pix.pixelformat) {
00218 av_log(ctx, AV_LOG_DEBUG, "The V4L2 driver changed the pixel format from 0x%08X to 0x%08X\n", pix_fmt, fmt.fmt.pix.pixelformat);
00219 res = -1;
00220 }
00221
00222 return res;
00223 }
00224
00225 static int first_field(int fd)
00226 {
00227 int res;
00228 v4l2_std_id std;
00229
00230 res = ioctl(fd, VIDIOC_G_STD, &std);
00231 if (res < 0) {
00232 return 0;
00233 }
00234 if (std & V4L2_STD_NTSC) {
00235 return 0;
00236 }
00237
00238 return 1;
00239 }
00240
00241 static uint32_t fmt_ff2v4l(enum PixelFormat pix_fmt, enum CodecID codec_id)
00242 {
00243 int i;
00244
00245 for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00246 if ((codec_id == CODEC_ID_NONE ||
00247 fmt_conversion_table[i].codec_id == codec_id) &&
00248 (pix_fmt == PIX_FMT_NONE ||
00249 fmt_conversion_table[i].ff_fmt == pix_fmt)) {
00250 return fmt_conversion_table[i].v4l2_fmt;
00251 }
00252 }
00253
00254 return 0;
00255 }
00256
00257 static enum PixelFormat fmt_v4l2ff(uint32_t v4l2_fmt, enum CodecID codec_id)
00258 {
00259 int i;
00260
00261 for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00262 if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt &&
00263 fmt_conversion_table[i].codec_id == codec_id) {
00264 return fmt_conversion_table[i].ff_fmt;
00265 }
00266 }
00267
00268 return PIX_FMT_NONE;
00269 }
00270
00271 static enum CodecID fmt_v4l2codec(uint32_t v4l2_fmt)
00272 {
00273 int i;
00274
00275 for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00276 if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt) {
00277 return fmt_conversion_table[i].codec_id;
00278 }
00279 }
00280
00281 return CODEC_ID_NONE;
00282 }
00283
00284 static int mmap_init(AVFormatContext *ctx)
00285 {
00286 struct video_data *s = ctx->priv_data;
00287 struct v4l2_requestbuffers req;
00288 int i, res;
00289
00290 memset(&req, 0, sizeof(struct v4l2_requestbuffers));
00291 req.count = desired_video_buffers;
00292 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00293 req.memory = V4L2_MEMORY_MMAP;
00294 res = ioctl (s->fd, VIDIOC_REQBUFS, &req);
00295 if (res < 0) {
00296 if (errno == EINVAL) {
00297 av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");
00298 } else {
00299 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
00300 }
00301
00302 return -1;
00303 }
00304
00305 if (req.count < 2) {
00306 av_log(ctx, AV_LOG_ERROR, "Insufficient buffer memory\n");
00307
00308 return -1;
00309 }
00310 s->buffers = req.count;
00311 s->buf_start = av_malloc(sizeof(void *) * s->buffers);
00312 if (s->buf_start == NULL) {
00313 av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
00314
00315 return -1;
00316 }
00317 s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers);
00318 if (s->buf_len == NULL) {
00319 av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
00320 av_free(s->buf_start);
00321
00322 return -1;
00323 }
00324
00325 for (i = 0; i < req.count; i++) {
00326 struct v4l2_buffer buf;
00327
00328 memset(&buf, 0, sizeof(struct v4l2_buffer));
00329 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00330 buf.memory = V4L2_MEMORY_MMAP;
00331 buf.index = i;
00332 res = ioctl (s->fd, VIDIOC_QUERYBUF, &buf);
00333 if (res < 0) {
00334 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
00335
00336 return -1;
00337 }
00338
00339 s->buf_len[i] = buf.length;
00340 if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) {
00341 av_log(ctx, AV_LOG_ERROR, "Buffer len [%d] = %d != %d\n", i, s->buf_len[i], s->frame_size);
00342
00343 return -1;
00344 }
00345 s->buf_start[i] = mmap (NULL, buf.length,
00346 PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
00347 if (s->buf_start[i] == MAP_FAILED) {
00348 av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
00349
00350 return -1;
00351 }
00352 }
00353
00354 return 0;
00355 }
00356
00357 static int read_init(AVFormatContext *ctx)
00358 {
00359 return -1;
00360 }
00361
00362 static void mmap_release_buffer(AVPacket *pkt)
00363 {
00364 struct v4l2_buffer buf;
00365 int res, fd;
00366 struct buff_data *buf_descriptor = pkt->priv;
00367
00368 if (pkt->data == NULL) {
00369 return;
00370 }
00371
00372 memset(&buf, 0, sizeof(struct v4l2_buffer));
00373 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00374 buf.memory = V4L2_MEMORY_MMAP;
00375 buf.index = buf_descriptor->index;
00376 fd = buf_descriptor->fd;
00377 av_free(buf_descriptor);
00378
00379 res = ioctl (fd, VIDIOC_QBUF, &buf);
00380 if (res < 0) {
00381 av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");
00382 }
00383 pkt->data = NULL;
00384 pkt->size = 0;
00385 }
00386
00387 static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
00388 {
00389 struct video_data *s = ctx->priv_data;
00390 struct v4l2_buffer buf;
00391 struct buff_data *buf_descriptor;
00392 int res;
00393
00394 memset(&buf, 0, sizeof(struct v4l2_buffer));
00395 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00396 buf.memory = V4L2_MEMORY_MMAP;
00397
00398
00399 while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
00400 if (res < 0) {
00401 if (errno == EAGAIN) {
00402 pkt->size = 0;
00403
00404 return AVERROR(EAGAIN);
00405 }
00406 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", strerror(errno));
00407
00408 return -1;
00409 }
00410 assert (buf.index < s->buffers);
00411 if (s->frame_size > 0 && buf.bytesused != s->frame_size) {
00412 av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size);
00413
00414 return -1;
00415 }
00416
00417
00418 pkt->data= s->buf_start[buf.index];
00419 pkt->size = buf.bytesused;
00420 pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
00421 pkt->destruct = mmap_release_buffer;
00422 buf_descriptor = av_malloc(sizeof(struct buff_data));
00423 if (buf_descriptor == NULL) {
00424
00425
00426
00427 av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
00428 res = ioctl (s->fd, VIDIOC_QBUF, &buf);
00429
00430 return -1;
00431 }
00432 buf_descriptor->fd = s->fd;
00433 buf_descriptor->index = buf.index;
00434 pkt->priv = buf_descriptor;
00435
00436 return s->buf_len[buf.index];
00437 }
00438
00439 static int read_frame(AVFormatContext *ctx, AVPacket *pkt)
00440 {
00441 return -1;
00442 }
00443
00444 static int mmap_start(AVFormatContext *ctx)
00445 {
00446 struct video_data *s = ctx->priv_data;
00447 enum v4l2_buf_type type;
00448 int i, res;
00449
00450 for (i = 0; i < s->buffers; i++) {
00451 struct v4l2_buffer buf;
00452
00453 memset(&buf, 0, sizeof(struct v4l2_buffer));
00454 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00455 buf.memory = V4L2_MEMORY_MMAP;
00456 buf.index = i;
00457
00458 res = ioctl (s->fd, VIDIOC_QBUF, &buf);
00459 if (res < 0) {
00460 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
00461
00462 return -1;
00463 }
00464 }
00465
00466 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00467 res = ioctl (s->fd, VIDIOC_STREAMON, &type);
00468 if (res < 0) {
00469 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno));
00470
00471 return -1;
00472 }
00473
00474 return 0;
00475 }
00476
00477 static void mmap_close(struct video_data *s)
00478 {
00479 enum v4l2_buf_type type;
00480 int i;
00481
00482 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00483
00484
00485
00486 ioctl(s->fd, VIDIOC_STREAMOFF, &type);
00487 for (i = 0; i < s->buffers; i++) {
00488 munmap(s->buf_start[i], s->buf_len[i]);
00489 }
00490 av_free(s->buf_start);
00491 av_free(s->buf_len);
00492 }
00493
00494 static int v4l2_set_parameters( AVFormatContext *s1, AVFormatParameters *ap )
00495 {
00496 struct video_data *s = s1->priv_data;
00497 struct v4l2_input input;
00498 struct v4l2_standard standard;
00499 int i;
00500
00501 if(ap->channel>=0) {
00502
00503 memset (&input, 0, sizeof (input));
00504 input.index = ap->channel;
00505 if(ioctl (s->fd, VIDIOC_ENUMINPUT, &input) < 0) {
00506 av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n");
00507 return AVERROR(EIO);
00508 }
00509
00510 av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n",
00511 ap->channel, input.name);
00512 if(ioctl (s->fd, VIDIOC_S_INPUT, &input.index) < 0 ) {
00513 av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set input(%d) failed\n",
00514 ap->channel);
00515 return AVERROR(EIO);
00516 }
00517 }
00518
00519 if(ap->standard) {
00520 av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
00521 ap->standard );
00522
00523 memset (&standard, 0, sizeof (standard));
00524 for(i=0;;i++) {
00525 standard.index = i;
00526 if (ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) {
00527 av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
00528 ap->standard);
00529 return AVERROR(EIO);
00530 }
00531
00532 if(!strcasecmp(standard.name, ap->standard)) {
00533 break;
00534 }
00535 }
00536
00537 av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s, id: %"PRIu64"\n",
00538 ap->standard, (uint64_t)standard.id);
00539 if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
00540 av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
00541 ap->standard);
00542 return AVERROR(EIO);
00543 }
00544 }
00545
00546 return 0;
00547 }
00548
00549 static uint32_t device_try_init(AVFormatContext *s1,
00550 const AVFormatParameters *ap,
00551 int *width,
00552 int *height,
00553 enum CodecID *codec_id)
00554 {
00555 uint32_t desired_format = fmt_ff2v4l(ap->pix_fmt, s1->video_codec_id);
00556
00557 if (desired_format == 0 ||
00558 device_init(s1, width, height, desired_format) < 0) {
00559 int i;
00560
00561 desired_format = 0;
00562 for (i = 0; i<FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00563 if (s1->video_codec_id == CODEC_ID_NONE ||
00564 fmt_conversion_table[i].codec_id == s1->video_codec_id) {
00565 desired_format = fmt_conversion_table[i].v4l2_fmt;
00566 if (device_init(s1, width, height, desired_format) >= 0) {
00567 break;
00568 }
00569 desired_format = 0;
00570 }
00571 }
00572 }
00573 if (desired_format != 0) {
00574 *codec_id = fmt_v4l2codec(desired_format);
00575 assert(*codec_id != CODEC_ID_NONE);
00576 }
00577
00578 return desired_format;
00579 }
00580
00581 static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
00582 {
00583 struct video_data *s = s1->priv_data;
00584 AVStream *st;
00585 int width, height;
00586 int res;
00587 uint32_t desired_format, capabilities;
00588 enum CodecID codec_id;
00589
00590 if (ap->width <= 0 || ap->height <= 0) {
00591 av_log(s1, AV_LOG_ERROR, "Wrong size (%dx%d)\n", ap->width, ap->height);
00592 return -1;
00593 }
00594
00595 width = ap->width;
00596 height = ap->height;
00597
00598 if(avcodec_check_dimensions(s1, ap->width, ap->height) < 0)
00599 return -1;
00600
00601 st = av_new_stream(s1, 0);
00602 if (!st) {
00603 return AVERROR(ENOMEM);
00604 }
00605 av_set_pts_info(st, 64, 1, 1000000);
00606
00607 s->width = width;
00608 s->height = height;
00609
00610 capabilities = 0;
00611 s->fd = device_open(s1, &capabilities);
00612 if (s->fd < 0) {
00613 return AVERROR(EIO);
00614 }
00615 av_log(s1, AV_LOG_INFO, "[%d]Capabilities: %x\n", s->fd, capabilities);
00616
00617 desired_format = device_try_init(s1, ap, &width, &height, &codec_id);
00618 if (desired_format == 0) {
00619 av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
00620 "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, ap->pix_fmt);
00621 close(s->fd);
00622
00623 return AVERROR(EIO);
00624 }
00625 s->frame_format = desired_format;
00626
00627 if( v4l2_set_parameters( s1, ap ) < 0 )
00628 return AVERROR(EIO);
00629
00630 st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id);
00631 s->frame_size = avpicture_get_size(st->codec->pix_fmt, width, height);
00632 if (capabilities & V4L2_CAP_STREAMING) {
00633 s->io_method = io_mmap;
00634 res = mmap_init(s1);
00635 if (res == 0) {
00636 res = mmap_start(s1);
00637 }
00638 } else {
00639 s->io_method = io_read;
00640 res = read_init(s1);
00641 }
00642 if (res < 0) {
00643 close(s->fd);
00644
00645 return AVERROR(EIO);
00646 }
00647 s->top_field_first = first_field(s->fd);
00648
00649 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00650 st->codec->codec_id = codec_id;
00651 st->codec->width = width;
00652 st->codec->height = height;
00653 st->codec->time_base.den = ap->time_base.den;
00654 st->codec->time_base.num = ap->time_base.num;
00655 st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;
00656
00657 return 0;
00658 }
00659
00660 static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt)
00661 {
00662 struct video_data *s = s1->priv_data;
00663 int res;
00664
00665 if (s->io_method == io_mmap) {
00666 av_init_packet(pkt);
00667 res = mmap_read_frame(s1, pkt);
00668 } else if (s->io_method == io_read) {
00669 if (av_new_packet(pkt, s->frame_size) < 0)
00670 return AVERROR(EIO);
00671
00672 res = read_frame(s1, pkt);
00673 } else {
00674 return AVERROR(EIO);
00675 }
00676 if (res < 0) {
00677 return res;
00678 }
00679
00680 if (s1->streams[0]->codec->coded_frame) {
00681 s1->streams[0]->codec->coded_frame->interlaced_frame = 1;
00682 s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first;
00683 }
00684
00685 return pkt->size;
00686 }
00687
00688 static int v4l2_read_close(AVFormatContext *s1)
00689 {
00690 struct video_data *s = s1->priv_data;
00691
00692 if (s->io_method == io_mmap) {
00693 mmap_close(s);
00694 }
00695
00696 close(s->fd);
00697 return 0;
00698 }
00699
00700 AVInputFormat v4l2_demuxer = {
00701 "video4linux2",
00702 NULL_IF_CONFIG_SMALL("Video4Linux2 device grab"),
00703 sizeof(struct video_data),
00704 NULL,
00705 v4l2_read_header,
00706 v4l2_read_packet,
00707 v4l2_read_close,
00708 .flags = AVFMT_NOFILE,
00709 };