• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavdevice/v4l2.c

Go to the documentation of this file.
00001 /*
00002  * Video4Linux2 grab interface
00003  * Copyright (c) 2000,2001 Fabrice Bellard
00004  * Copyright (c) 2006 Luca Abeni
00005  *
00006  * Part of this file is based on the V4L2 video capture example
00007  * (http://v4l2spec.bytesex.org/v4l2spec/capture.c)
00008  *
00009  * Thanks to Michael Niedermayer for providing the mapping between
00010  * V4L2_PIX_FMT_* and PIX_FMT_*
00011  *
00012  *
00013  * This file is part of FFmpeg.
00014  *
00015  * FFmpeg is free software; you can redistribute it and/or
00016  * modify it under the terms of the GNU Lesser General Public
00017  * License as published by the Free Software Foundation; either
00018  * version 2.1 of the License, or (at your option) any later version.
00019  *
00020  * FFmpeg is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00023  * Lesser General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU Lesser General Public
00026  * License along with FFmpeg; if not, write to the Free Software
00027  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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; /* V4L2_PIX_FMT_* */
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, err;
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 AVERROR(errno);
00168     }
00169 
00170     res = ioctl(fd, VIDIOC_QUERYCAP, &cap);
00171     // ENOIOCTLCMD definition only availble on __KERNEL__
00172     if (res < 0 && ((err = errno) == 515)) {
00173         av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n");
00174         close(fd);
00175 
00176         return AVERROR(515);
00177     }
00178     if (res < 0) {
00179         av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
00180                  strerror(errno));
00181         close(fd);
00182 
00183         return AVERROR(err);
00184     }
00185     if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
00186         av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n");
00187         close(fd);
00188 
00189         return AVERROR(ENODEV);
00190     }
00191     *capabilities = cap.capabilities;
00192 
00193     return fd;
00194 }
00195 
00196 static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pix_fmt)
00197 {
00198     struct video_data *s = ctx->priv_data;
00199     int fd = s->fd;
00200     struct v4l2_format fmt;
00201     int res;
00202 
00203     memset(&fmt, 0, sizeof(struct v4l2_format));
00204     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00205     fmt.fmt.pix.width = *width;
00206     fmt.fmt.pix.height = *height;
00207     fmt.fmt.pix.pixelformat = pix_fmt;
00208     fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
00209     res = ioctl(fd, VIDIOC_S_FMT, &fmt);
00210     if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
00211         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);
00212         *width = fmt.fmt.pix.width;
00213         *height = fmt.fmt.pix.height;
00214     }
00215 
00216     if (pix_fmt != fmt.fmt.pix.pixelformat) {
00217         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);
00218         res = -1;
00219     }
00220 
00221     return res;
00222 }
00223 
00224 static int first_field(int fd)
00225 {
00226     int res;
00227     v4l2_std_id std;
00228 
00229     res = ioctl(fd, VIDIOC_G_STD, &std);
00230     if (res < 0) {
00231         return 0;
00232     }
00233     if (std & V4L2_STD_NTSC) {
00234         return 0;
00235     }
00236 
00237     return 1;
00238 }
00239 
00240 static uint32_t fmt_ff2v4l(enum PixelFormat pix_fmt, enum CodecID codec_id)
00241 {
00242     int i;
00243 
00244     for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00245         if ((codec_id == CODEC_ID_NONE ||
00246              fmt_conversion_table[i].codec_id == codec_id) &&
00247             (pix_fmt == PIX_FMT_NONE ||
00248              fmt_conversion_table[i].ff_fmt == pix_fmt)) {
00249             return fmt_conversion_table[i].v4l2_fmt;
00250         }
00251     }
00252 
00253     return 0;
00254 }
00255 
00256 static enum PixelFormat fmt_v4l2ff(uint32_t v4l2_fmt, enum CodecID codec_id)
00257 {
00258     int i;
00259 
00260     for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00261         if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt &&
00262             fmt_conversion_table[i].codec_id == codec_id) {
00263             return fmt_conversion_table[i].ff_fmt;
00264         }
00265     }
00266 
00267     return PIX_FMT_NONE;
00268 }
00269 
00270 static enum CodecID fmt_v4l2codec(uint32_t v4l2_fmt)
00271 {
00272     int i;
00273 
00274     for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00275         if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt) {
00276             return fmt_conversion_table[i].codec_id;
00277         }
00278     }
00279 
00280     return CODEC_ID_NONE;
00281 }
00282 
00283 static int mmap_init(AVFormatContext *ctx)
00284 {
00285     struct video_data *s = ctx->priv_data;
00286     struct v4l2_requestbuffers req;
00287     int i, res;
00288 
00289     memset(&req, 0, sizeof(struct v4l2_requestbuffers));
00290     req.count = desired_video_buffers;
00291     req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00292     req.memory = V4L2_MEMORY_MMAP;
00293     res = ioctl (s->fd, VIDIOC_REQBUFS, &req);
00294     if (res < 0) {
00295         if (errno == EINVAL) {
00296             av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");
00297         } else {
00298             av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
00299         }
00300 
00301         return AVERROR(errno);
00302     }
00303 
00304     if (req.count < 2) {
00305         av_log(ctx, AV_LOG_ERROR, "Insufficient buffer memory\n");
00306 
00307         return AVERROR(ENOMEM);
00308     }
00309     s->buffers = req.count;
00310     s->buf_start = av_malloc(sizeof(void *) * s->buffers);
00311     if (s->buf_start == NULL) {
00312         av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
00313 
00314         return AVERROR(ENOMEM);
00315     }
00316     s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers);
00317     if (s->buf_len == NULL) {
00318         av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
00319         av_free(s->buf_start);
00320 
00321         return AVERROR(ENOMEM);
00322     }
00323 
00324     for (i = 0; i < req.count; i++) {
00325         struct v4l2_buffer buf;
00326 
00327         memset(&buf, 0, sizeof(struct v4l2_buffer));
00328         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00329         buf.memory = V4L2_MEMORY_MMAP;
00330         buf.index = i;
00331         res = ioctl (s->fd, VIDIOC_QUERYBUF, &buf);
00332         if (res < 0) {
00333             av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
00334 
00335             return AVERROR(errno);
00336         }
00337 
00338         s->buf_len[i] = buf.length;
00339         if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) {
00340             av_log(ctx, AV_LOG_ERROR, "Buffer len [%d] = %d != %d\n", i, s->buf_len[i], s->frame_size);
00341 
00342             return -1;
00343         }
00344         s->buf_start[i] = mmap (NULL, buf.length,
00345                         PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
00346         if (s->buf_start[i] == MAP_FAILED) {
00347             av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
00348 
00349             return AVERROR(errno);
00350         }
00351     }
00352 
00353     return 0;
00354 }
00355 
00356 static int read_init(AVFormatContext *ctx)
00357 {
00358     return -1;
00359 }
00360 
00361 static void mmap_release_buffer(AVPacket *pkt)
00362 {
00363     struct v4l2_buffer buf;
00364     int res, fd;
00365     struct buff_data *buf_descriptor = pkt->priv;
00366 
00367     if (pkt->data == NULL) {
00368          return;
00369     }
00370 
00371     memset(&buf, 0, sizeof(struct v4l2_buffer));
00372     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00373     buf.memory = V4L2_MEMORY_MMAP;
00374     buf.index = buf_descriptor->index;
00375     fd = buf_descriptor->fd;
00376     av_free(buf_descriptor);
00377 
00378     res = ioctl (fd, VIDIOC_QBUF, &buf);
00379     if (res < 0) {
00380         av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");
00381     }
00382     pkt->data = NULL;
00383     pkt->size = 0;
00384 }
00385 
00386 static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
00387 {
00388     struct video_data *s = ctx->priv_data;
00389     struct v4l2_buffer buf;
00390     struct buff_data *buf_descriptor;
00391     int res;
00392 
00393     memset(&buf, 0, sizeof(struct v4l2_buffer));
00394     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00395     buf.memory = V4L2_MEMORY_MMAP;
00396 
00397     /* FIXME: Some special treatment might be needed in case of loss of signal... */
00398     while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
00399     if (res < 0) {
00400         if (errno == EAGAIN) {
00401             pkt->size = 0;
00402 
00403             return AVERROR(EAGAIN);
00404         }
00405         av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", strerror(errno));
00406 
00407         return AVERROR(errno);
00408     }
00409     assert (buf.index < s->buffers);
00410     if (s->frame_size > 0 && buf.bytesused != s->frame_size) {
00411         av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size);
00412 
00413         return AVERROR_INVALIDDATA;
00414     }
00415 
00416     /* Image is at s->buff_start[buf.index] */
00417     pkt->data= s->buf_start[buf.index];
00418     pkt->size = buf.bytesused;
00419     pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
00420     pkt->destruct = mmap_release_buffer;
00421     buf_descriptor = av_malloc(sizeof(struct buff_data));
00422     if (buf_descriptor == NULL) {
00423         /* Something went wrong... Since av_malloc() failed, we cannot even
00424          * allocate a buffer for memcopying into it
00425          */
00426         av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
00427         res = ioctl (s->fd, VIDIOC_QBUF, &buf);
00428 
00429         return AVERROR(ENOMEM);
00430     }
00431     buf_descriptor->fd = s->fd;
00432     buf_descriptor->index = buf.index;
00433     pkt->priv = buf_descriptor;
00434 
00435     return s->buf_len[buf.index];
00436 }
00437 
00438 static int read_frame(AVFormatContext *ctx, AVPacket *pkt)
00439 {
00440     return -1;
00441 }
00442 
00443 static int mmap_start(AVFormatContext *ctx)
00444 {
00445     struct video_data *s = ctx->priv_data;
00446     enum v4l2_buf_type type;
00447     int i, res;
00448 
00449     for (i = 0; i < s->buffers; i++) {
00450         struct v4l2_buffer buf;
00451 
00452         memset(&buf, 0, sizeof(struct v4l2_buffer));
00453         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00454         buf.memory = V4L2_MEMORY_MMAP;
00455         buf.index  = i;
00456 
00457         res = ioctl (s->fd, VIDIOC_QBUF, &buf);
00458         if (res < 0) {
00459             av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
00460 
00461             return AVERROR(errno);
00462         }
00463     }
00464 
00465     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00466     res = ioctl (s->fd, VIDIOC_STREAMON, &type);
00467     if (res < 0) {
00468         av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno));
00469 
00470         return AVERROR(errno);
00471     }
00472 
00473     return 0;
00474 }
00475 
00476 static void mmap_close(struct video_data *s)
00477 {
00478     enum v4l2_buf_type type;
00479     int i;
00480 
00481     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00482     /* We do not check for the result, because we could
00483      * not do anything about it anyway...
00484      */
00485     ioctl(s->fd, VIDIOC_STREAMOFF, &type);
00486     for (i = 0; i < s->buffers; i++) {
00487         munmap(s->buf_start[i], s->buf_len[i]);
00488     }
00489     av_free(s->buf_start);
00490     av_free(s->buf_len);
00491 }
00492 
00493 static int v4l2_set_parameters( AVFormatContext *s1, AVFormatParameters *ap )
00494 {
00495     struct video_data *s = s1->priv_data;
00496     struct v4l2_input input;
00497     struct v4l2_standard standard;
00498     int i;
00499 
00500     if(ap->channel>=0) {
00501         /* set tv video input */
00502         memset (&input, 0, sizeof (input));
00503         input.index = ap->channel;
00504         if(ioctl (s->fd, VIDIOC_ENUMINPUT, &input) < 0) {
00505             av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n");
00506             return AVERROR(EIO);
00507         }
00508 
00509         av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n",
00510                ap->channel, input.name);
00511         if(ioctl (s->fd, VIDIOC_S_INPUT, &input.index) < 0 ) {
00512             av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set input(%d) failed\n",
00513                    ap->channel);
00514             return AVERROR(EIO);
00515         }
00516     }
00517 
00518     if(ap->standard) {
00519         av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
00520                ap->standard );
00521         /* set tv standard */
00522         memset (&standard, 0, sizeof (standard));
00523         for(i=0;;i++) {
00524             standard.index = i;
00525             if (ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) {
00526                 av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
00527                        ap->standard);
00528                 return AVERROR(EIO);
00529             }
00530 
00531             if(!strcasecmp(standard.name, ap->standard)) {
00532                 break;
00533             }
00534         }
00535 
00536         av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s, id: %"PRIu64"\n",
00537                ap->standard, (uint64_t)standard.id);
00538         if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
00539             av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
00540                    ap->standard);
00541             return AVERROR(EIO);
00542         }
00543     }
00544 
00545     return 0;
00546 }
00547 
00548 static uint32_t device_try_init(AVFormatContext *s1,
00549                                 const AVFormatParameters *ap,
00550                                 int *width,
00551                                 int *height,
00552                                 enum CodecID *codec_id)
00553 {
00554     uint32_t desired_format = fmt_ff2v4l(ap->pix_fmt, s1->video_codec_id);
00555 
00556     if (desired_format == 0 ||
00557         device_init(s1, width, height, desired_format) < 0) {
00558         int i;
00559 
00560         desired_format = 0;
00561         for (i = 0; i<FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
00562             if (s1->video_codec_id == CODEC_ID_NONE ||
00563                 fmt_conversion_table[i].codec_id == s1->video_codec_id) {
00564                 desired_format = fmt_conversion_table[i].v4l2_fmt;
00565                 if (device_init(s1, width, height, desired_format) >= 0) {
00566                     break;
00567                 }
00568                 desired_format = 0;
00569             }
00570         }
00571     }
00572     if (desired_format != 0) {
00573         *codec_id = fmt_v4l2codec(desired_format);
00574         assert(*codec_id != CODEC_ID_NONE);
00575     }
00576 
00577     return desired_format;
00578 }
00579 
00580 static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
00581 {
00582     struct video_data *s = s1->priv_data;
00583     AVStream *st;
00584     int res;
00585     uint32_t desired_format, capabilities;
00586     enum CodecID codec_id;
00587 
00588     st = av_new_stream(s1, 0);
00589     if (!st) {
00590         return AVERROR(ENOMEM);
00591     }
00592     av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
00593 
00594     s->width  = ap->width;
00595     s->height = ap->height;
00596 
00597     capabilities = 0;
00598     s->fd = device_open(s1, &capabilities);
00599     if (s->fd < 0) {
00600         return AVERROR(EIO);
00601     }
00602     av_log(s1, AV_LOG_VERBOSE, "[%d]Capabilities: %x\n", s->fd, capabilities);
00603 
00604     if (!s->width && !s->height) {
00605         struct v4l2_format fmt;
00606 
00607         av_log(s1, AV_LOG_VERBOSE, "Querying the device for the current frame size\n");
00608         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00609         if (ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) {
00610             av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", strerror(errno));
00611             return AVERROR(errno);
00612         }
00613         s->width  = fmt.fmt.pix.width;
00614         s->height = fmt.fmt.pix.height;
00615         av_log(s1, AV_LOG_VERBOSE, "Setting frame size to %dx%d\n", s->width, s->height);
00616     }
00617 
00618     desired_format = device_try_init(s1, ap, &s->width, &s->height, &codec_id);
00619     if (desired_format == 0) {
00620         av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
00621                "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, ap->pix_fmt);
00622         close(s->fd);
00623 
00624         return AVERROR(EIO);
00625     }
00626     if (avcodec_check_dimensions(s1, s->width, s->height) < 0)
00627         return AVERROR(EINVAL);
00628     s->frame_format = desired_format;
00629 
00630     if( v4l2_set_parameters( s1, ap ) < 0 )
00631         return AVERROR(EIO);
00632 
00633     st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id);
00634     s->frame_size = avpicture_get_size(st->codec->pix_fmt, s->width, s->height);
00635     if (capabilities & V4L2_CAP_STREAMING) {
00636         s->io_method = io_mmap;
00637         res = mmap_init(s1);
00638         if (res == 0) {
00639             res = mmap_start(s1);
00640         }
00641     } else {
00642         s->io_method = io_read;
00643         res = read_init(s1);
00644     }
00645     if (res < 0) {
00646         close(s->fd);
00647 
00648         return AVERROR(EIO);
00649     }
00650     s->top_field_first = first_field(s->fd);
00651 
00652     st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00653     st->codec->codec_id = codec_id;
00654     st->codec->width = s->width;
00655     st->codec->height = s->height;
00656     st->codec->time_base.den = ap->time_base.den;
00657     st->codec->time_base.num = ap->time_base.num;
00658     st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;
00659 
00660     return 0;
00661 }
00662 
00663 static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt)
00664 {
00665     struct video_data *s = s1->priv_data;
00666     int res;
00667 
00668     if (s->io_method == io_mmap) {
00669         av_init_packet(pkt);
00670         res = mmap_read_frame(s1, pkt);
00671     } else if (s->io_method == io_read) {
00672         if (av_new_packet(pkt, s->frame_size) < 0)
00673             return AVERROR(EIO);
00674 
00675         res = read_frame(s1, pkt);
00676     } else {
00677         return AVERROR(EIO);
00678     }
00679     if (res < 0) {
00680         return res;
00681     }
00682 
00683     if (s1->streams[0]->codec->coded_frame) {
00684         s1->streams[0]->codec->coded_frame->interlaced_frame = 1;
00685         s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first;
00686     }
00687 
00688     return pkt->size;
00689 }
00690 
00691 static int v4l2_read_close(AVFormatContext *s1)
00692 {
00693     struct video_data *s = s1->priv_data;
00694 
00695     if (s->io_method == io_mmap) {
00696         mmap_close(s);
00697     }
00698 
00699     close(s->fd);
00700     return 0;
00701 }
00702 
00703 AVInputFormat v4l2_demuxer = {
00704     "video4linux2",
00705     NULL_IF_CONFIG_SMALL("Video4Linux2 device grab"),
00706     sizeof(struct video_data),
00707     NULL,
00708     v4l2_read_header,
00709     v4l2_read_packet,
00710     v4l2_read_close,
00711     .flags = AVFMT_NOFILE,
00712 };

Generated on Fri Sep 16 2011 17:17:47 for FFmpeg by  doxygen 1.7.1