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