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