ffmpeg / libavdevice / v4l2.c @ 075a5560
History | View | Annotate | Download (20.2 KB)
1 |
/*
|
---|---|
2 |
* Video4Linux2 grab interface
|
3 |
* Copyright (c) 2000,2001 Fabrice Bellard
|
4 |
* Copyright (c) 2006 Luca Abeni
|
5 |
*
|
6 |
* Part of this file is based on the V4L2 video capture example
|
7 |
* (http://v4l2spec.bytesex.org/v4l2spec/capture.c)
|
8 |
*
|
9 |
* Thanks to Michael Niedermayer for providing the mapping between
|
10 |
* V4L2_PIX_FMT_* and PIX_FMT_*
|
11 |
*
|
12 |
*
|
13 |
* This file is part of FFmpeg.
|
14 |
*
|
15 |
* FFmpeg is free software; you can redistribute it and/or
|
16 |
* modify it under the terms of the GNU Lesser General Public
|
17 |
* License as published by the Free Software Foundation; either
|
18 |
* version 2.1 of the License, or (at your option) any later version.
|
19 |
*
|
20 |
* FFmpeg is distributed in the hope that it will be useful,
|
21 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
22 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
23 |
* Lesser General Public License for more details.
|
24 |
*
|
25 |
* You should have received a copy of the GNU Lesser General Public
|
26 |
* License along with FFmpeg; if not, write to the Free Software
|
27 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
28 |
*/
|
29 |
|
30 |
#undef __STRICT_ANSI__ //workaround due to broken kernel headers |
31 |
#include "config.h" |
32 |
#include "libavformat/avformat.h" |
33 |
#include <unistd.h> |
34 |
#include <fcntl.h> |
35 |
#include <sys/ioctl.h> |
36 |
#include <sys/mman.h> |
37 |
#include <sys/time.h> |
38 |
#if HAVE_SYS_VIDEOIO_H
|
39 |
#include <sys/videoio.h> |
40 |
#else
|
41 |
#include <asm/types.h> |
42 |
#include <linux/videodev2.h> |
43 |
#endif
|
44 |
#include <time.h> |
45 |
#include <strings.h> |
46 |
#include "libavutil/imgutils.h" |
47 |
|
48 |
static const int desired_video_buffers = 256; |
49 |
|
50 |
enum io_method {
|
51 |
io_read, |
52 |
io_mmap, |
53 |
io_userptr |
54 |
}; |
55 |
|
56 |
struct video_data {
|
57 |
int fd;
|
58 |
int frame_format; /* V4L2_PIX_FMT_* */ |
59 |
enum io_method io_method;
|
60 |
int width, height;
|
61 |
int frame_size;
|
62 |
int top_field_first;
|
63 |
|
64 |
int buffers;
|
65 |
void **buf_start;
|
66 |
unsigned int *buf_len; |
67 |
}; |
68 |
|
69 |
struct buff_data {
|
70 |
int index;
|
71 |
int fd;
|
72 |
}; |
73 |
|
74 |
struct fmt_map {
|
75 |
enum PixelFormat ff_fmt;
|
76 |
enum CodecID codec_id;
|
77 |
uint32_t v4l2_fmt; |
78 |
}; |
79 |
|
80 |
static struct fmt_map fmt_conversion_table[] = { |
81 |
//ff_fmt codec_id v4l2_fmt
|
82 |
{ PIX_FMT_YUV420P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV420 }, |
83 |
{ PIX_FMT_YUV422P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV422P }, |
84 |
{ PIX_FMT_YUYV422, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUYV }, |
85 |
{ PIX_FMT_UYVY422, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_UYVY }, |
86 |
{ PIX_FMT_YUV411P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV411P }, |
87 |
{ PIX_FMT_YUV410P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV410 }, |
88 |
{ PIX_FMT_RGB555, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB555 }, |
89 |
{ PIX_FMT_RGB565, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB565 }, |
90 |
{ PIX_FMT_BGR24, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_BGR24 }, |
91 |
{ PIX_FMT_RGB24, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB24 }, |
92 |
{ PIX_FMT_BGRA, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_BGR32 }, |
93 |
{ PIX_FMT_GRAY8, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_GREY }, |
94 |
{ PIX_FMT_NV12, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV12 }, |
95 |
{ PIX_FMT_NONE, CODEC_ID_MJPEG, V4L2_PIX_FMT_MJPEG }, |
96 |
{ PIX_FMT_NONE, CODEC_ID_MJPEG, V4L2_PIX_FMT_JPEG }, |
97 |
}; |
98 |
|
99 |
static int device_open(AVFormatContext *ctx, uint32_t *capabilities) |
100 |
{ |
101 |
struct v4l2_capability cap;
|
102 |
int fd;
|
103 |
int res, err;
|
104 |
int flags = O_RDWR;
|
105 |
|
106 |
if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
|
107 |
flags |= O_NONBLOCK; |
108 |
} |
109 |
fd = open(ctx->filename, flags, 0);
|
110 |
if (fd < 0) { |
111 |
av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
|
112 |
ctx->filename, strerror(errno)); |
113 |
|
114 |
return AVERROR(errno);
|
115 |
} |
116 |
|
117 |
res = ioctl(fd, VIDIOC_QUERYCAP, &cap); |
118 |
// ENOIOCTLCMD definition only availble on __KERNEL__
|
119 |
if (res < 0 && ((err = errno) == 515)) { |
120 |
av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n");
|
121 |
close(fd); |
122 |
|
123 |
return AVERROR(515); |
124 |
} |
125 |
if (res < 0) { |
126 |
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
|
127 |
strerror(errno)); |
128 |
close(fd); |
129 |
|
130 |
return AVERROR(err);
|
131 |
} |
132 |
if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { |
133 |
av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n");
|
134 |
close(fd); |
135 |
|
136 |
return AVERROR(ENODEV);
|
137 |
} |
138 |
*capabilities = cap.capabilities; |
139 |
|
140 |
return fd;
|
141 |
} |
142 |
|
143 |
static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pix_fmt) |
144 |
{ |
145 |
struct video_data *s = ctx->priv_data;
|
146 |
int fd = s->fd;
|
147 |
struct v4l2_format fmt;
|
148 |
int res;
|
149 |
|
150 |
memset(&fmt, 0, sizeof(struct v4l2_format)); |
151 |
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
152 |
fmt.fmt.pix.width = *width; |
153 |
fmt.fmt.pix.height = *height; |
154 |
fmt.fmt.pix.pixelformat = pix_fmt; |
155 |
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; |
156 |
res = ioctl(fd, VIDIOC_S_FMT, &fmt); |
157 |
if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
|
158 |
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);
|
159 |
*width = fmt.fmt.pix.width; |
160 |
*height = fmt.fmt.pix.height; |
161 |
} |
162 |
|
163 |
if (pix_fmt != fmt.fmt.pix.pixelformat) {
|
164 |
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);
|
165 |
res = -1;
|
166 |
} |
167 |
|
168 |
return res;
|
169 |
} |
170 |
|
171 |
static int first_field(int fd) |
172 |
{ |
173 |
int res;
|
174 |
v4l2_std_id std; |
175 |
|
176 |
res = ioctl(fd, VIDIOC_G_STD, &std); |
177 |
if (res < 0) { |
178 |
return 0; |
179 |
} |
180 |
if (std & V4L2_STD_NTSC) {
|
181 |
return 0; |
182 |
} |
183 |
|
184 |
return 1; |
185 |
} |
186 |
|
187 |
static uint32_t fmt_ff2v4l(enum PixelFormat pix_fmt, enum CodecID codec_id) |
188 |
{ |
189 |
int i;
|
190 |
|
191 |
for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) { |
192 |
if ((codec_id == CODEC_ID_NONE ||
|
193 |
fmt_conversion_table[i].codec_id == codec_id) && |
194 |
(pix_fmt == PIX_FMT_NONE || |
195 |
fmt_conversion_table[i].ff_fmt == pix_fmt)) { |
196 |
return fmt_conversion_table[i].v4l2_fmt;
|
197 |
} |
198 |
} |
199 |
|
200 |
return 0; |
201 |
} |
202 |
|
203 |
static enum PixelFormat fmt_v4l2ff(uint32_t v4l2_fmt, enum CodecID codec_id) |
204 |
{ |
205 |
int i;
|
206 |
|
207 |
for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) { |
208 |
if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt &&
|
209 |
fmt_conversion_table[i].codec_id == codec_id) { |
210 |
return fmt_conversion_table[i].ff_fmt;
|
211 |
} |
212 |
} |
213 |
|
214 |
return PIX_FMT_NONE;
|
215 |
} |
216 |
|
217 |
static enum CodecID fmt_v4l2codec(uint32_t v4l2_fmt) |
218 |
{ |
219 |
int i;
|
220 |
|
221 |
for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) { |
222 |
if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt) {
|
223 |
return fmt_conversion_table[i].codec_id;
|
224 |
} |
225 |
} |
226 |
|
227 |
return CODEC_ID_NONE;
|
228 |
} |
229 |
|
230 |
static int mmap_init(AVFormatContext *ctx) |
231 |
{ |
232 |
struct video_data *s = ctx->priv_data;
|
233 |
struct v4l2_requestbuffers req;
|
234 |
int i, res;
|
235 |
|
236 |
memset(&req, 0, sizeof(struct v4l2_requestbuffers)); |
237 |
req.count = desired_video_buffers; |
238 |
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
239 |
req.memory = V4L2_MEMORY_MMAP; |
240 |
res = ioctl(s->fd, VIDIOC_REQBUFS, &req); |
241 |
if (res < 0) { |
242 |
if (errno == EINVAL) {
|
243 |
av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");
|
244 |
} else {
|
245 |
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
|
246 |
} |
247 |
|
248 |
return AVERROR(errno);
|
249 |
} |
250 |
|
251 |
if (req.count < 2) { |
252 |
av_log(ctx, AV_LOG_ERROR, "Insufficient buffer memory\n");
|
253 |
|
254 |
return AVERROR(ENOMEM);
|
255 |
} |
256 |
s->buffers = req.count; |
257 |
s->buf_start = av_malloc(sizeof(void *) * s->buffers); |
258 |
if (s->buf_start == NULL) { |
259 |
av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
|
260 |
|
261 |
return AVERROR(ENOMEM);
|
262 |
} |
263 |
s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers); |
264 |
if (s->buf_len == NULL) { |
265 |
av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
|
266 |
av_free(s->buf_start); |
267 |
|
268 |
return AVERROR(ENOMEM);
|
269 |
} |
270 |
|
271 |
for (i = 0; i < req.count; i++) { |
272 |
struct v4l2_buffer buf;
|
273 |
|
274 |
memset(&buf, 0, sizeof(struct v4l2_buffer)); |
275 |
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
276 |
buf.memory = V4L2_MEMORY_MMAP; |
277 |
buf.index = i; |
278 |
res = ioctl(s->fd, VIDIOC_QUERYBUF, &buf); |
279 |
if (res < 0) { |
280 |
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
|
281 |
|
282 |
return AVERROR(errno);
|
283 |
} |
284 |
|
285 |
s->buf_len[i] = buf.length; |
286 |
if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) { |
287 |
av_log(ctx, AV_LOG_ERROR, "Buffer len [%d] = %d != %d\n", i, s->buf_len[i], s->frame_size);
|
288 |
|
289 |
return -1; |
290 |
} |
291 |
s->buf_start[i] = mmap (NULL, buf.length,
|
292 |
PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset); |
293 |
if (s->buf_start[i] == MAP_FAILED) {
|
294 |
av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
|
295 |
|
296 |
return AVERROR(errno);
|
297 |
} |
298 |
} |
299 |
|
300 |
return 0; |
301 |
} |
302 |
|
303 |
static int read_init(AVFormatContext *ctx) |
304 |
{ |
305 |
return -1; |
306 |
} |
307 |
|
308 |
static void mmap_release_buffer(AVPacket *pkt) |
309 |
{ |
310 |
struct v4l2_buffer buf;
|
311 |
int res, fd;
|
312 |
struct buff_data *buf_descriptor = pkt->priv;
|
313 |
|
314 |
if (pkt->data == NULL) { |
315 |
return;
|
316 |
} |
317 |
|
318 |
memset(&buf, 0, sizeof(struct v4l2_buffer)); |
319 |
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
320 |
buf.memory = V4L2_MEMORY_MMAP; |
321 |
buf.index = buf_descriptor->index; |
322 |
fd = buf_descriptor->fd; |
323 |
av_free(buf_descriptor); |
324 |
|
325 |
res = ioctl(fd, VIDIOC_QBUF, &buf); |
326 |
if (res < 0) { |
327 |
av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno)); |
328 |
} |
329 |
pkt->data = NULL;
|
330 |
pkt->size = 0;
|
331 |
} |
332 |
|
333 |
static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) |
334 |
{ |
335 |
struct video_data *s = ctx->priv_data;
|
336 |
struct v4l2_buffer buf;
|
337 |
struct buff_data *buf_descriptor;
|
338 |
int res;
|
339 |
|
340 |
memset(&buf, 0, sizeof(struct v4l2_buffer)); |
341 |
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
342 |
buf.memory = V4L2_MEMORY_MMAP; |
343 |
|
344 |
/* FIXME: Some special treatment might be needed in case of loss of signal... */
|
345 |
while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR)); |
346 |
if (res < 0) { |
347 |
if (errno == EAGAIN) {
|
348 |
pkt->size = 0;
|
349 |
|
350 |
return AVERROR(EAGAIN);
|
351 |
} |
352 |
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", strerror(errno));
|
353 |
|
354 |
return AVERROR(errno);
|
355 |
} |
356 |
assert (buf.index < s->buffers); |
357 |
if (s->frame_size > 0 && buf.bytesused != s->frame_size) { |
358 |
av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size);
|
359 |
|
360 |
return AVERROR_INVALIDDATA;
|
361 |
} |
362 |
|
363 |
/* Image is at s->buff_start[buf.index] */
|
364 |
pkt->data= s->buf_start[buf.index]; |
365 |
pkt->size = buf.bytesused; |
366 |
pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
|
367 |
pkt->destruct = mmap_release_buffer; |
368 |
buf_descriptor = av_malloc(sizeof(struct buff_data)); |
369 |
if (buf_descriptor == NULL) { |
370 |
/* Something went wrong... Since av_malloc() failed, we cannot even
|
371 |
* allocate a buffer for memcopying into it
|
372 |
*/
|
373 |
av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
|
374 |
res = ioctl(s->fd, VIDIOC_QBUF, &buf); |
375 |
|
376 |
return AVERROR(ENOMEM);
|
377 |
} |
378 |
buf_descriptor->fd = s->fd; |
379 |
buf_descriptor->index = buf.index; |
380 |
pkt->priv = buf_descriptor; |
381 |
|
382 |
return s->buf_len[buf.index];
|
383 |
} |
384 |
|
385 |
static int read_frame(AVFormatContext *ctx, AVPacket *pkt) |
386 |
{ |
387 |
return -1; |
388 |
} |
389 |
|
390 |
static int mmap_start(AVFormatContext *ctx) |
391 |
{ |
392 |
struct video_data *s = ctx->priv_data;
|
393 |
enum v4l2_buf_type type;
|
394 |
int i, res;
|
395 |
|
396 |
for (i = 0; i < s->buffers; i++) { |
397 |
struct v4l2_buffer buf;
|
398 |
|
399 |
memset(&buf, 0, sizeof(struct v4l2_buffer)); |
400 |
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
401 |
buf.memory = V4L2_MEMORY_MMAP; |
402 |
buf.index = i; |
403 |
|
404 |
res = ioctl(s->fd, VIDIOC_QBUF, &buf); |
405 |
if (res < 0) { |
406 |
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
|
407 |
|
408 |
return AVERROR(errno);
|
409 |
} |
410 |
} |
411 |
|
412 |
type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
413 |
res = ioctl(s->fd, VIDIOC_STREAMON, &type); |
414 |
if (res < 0) { |
415 |
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno));
|
416 |
|
417 |
return AVERROR(errno);
|
418 |
} |
419 |
|
420 |
return 0; |
421 |
} |
422 |
|
423 |
static void mmap_close(struct video_data *s) |
424 |
{ |
425 |
enum v4l2_buf_type type;
|
426 |
int i;
|
427 |
|
428 |
type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
429 |
/* We do not check for the result, because we could
|
430 |
* not do anything about it anyway...
|
431 |
*/
|
432 |
ioctl(s->fd, VIDIOC_STREAMOFF, &type); |
433 |
for (i = 0; i < s->buffers; i++) { |
434 |
munmap(s->buf_start[i], s->buf_len[i]); |
435 |
} |
436 |
av_free(s->buf_start); |
437 |
av_free(s->buf_len); |
438 |
} |
439 |
|
440 |
static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) |
441 |
{ |
442 |
struct video_data *s = s1->priv_data;
|
443 |
struct v4l2_input input;
|
444 |
struct v4l2_standard standard;
|
445 |
struct v4l2_streamparm streamparm = { 0 }; |
446 |
struct v4l2_fract *tpf = &streamparm.parm.capture.timeperframe;
|
447 |
int i;
|
448 |
|
449 |
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
450 |
|
451 |
if (ap->channel>=0) { |
452 |
/* set tv video input */
|
453 |
memset (&input, 0, sizeof (input)); |
454 |
input.index = ap->channel; |
455 |
if (ioctl(s->fd, VIDIOC_ENUMINPUT, &input) < 0) { |
456 |
av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n");
|
457 |
return AVERROR(EIO);
|
458 |
} |
459 |
|
460 |
av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n",
|
461 |
ap->channel, input.name); |
462 |
if (ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) { |
463 |
av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set input(%d) failed\n",
|
464 |
ap->channel); |
465 |
return AVERROR(EIO);
|
466 |
} |
467 |
} |
468 |
|
469 |
if (ap->standard) {
|
470 |
av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
|
471 |
ap->standard); |
472 |
/* set tv standard */
|
473 |
memset (&standard, 0, sizeof (standard)); |
474 |
for(i=0;;i++) { |
475 |
standard.index = i; |
476 |
if (ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) { |
477 |
av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
|
478 |
ap->standard); |
479 |
return AVERROR(EIO);
|
480 |
} |
481 |
|
482 |
if (!strcasecmp(standard.name, ap->standard)) {
|
483 |
break;
|
484 |
} |
485 |
} |
486 |
|
487 |
av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s, id: %"PRIu64"\n", |
488 |
ap->standard, (uint64_t)standard.id); |
489 |
if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) { |
490 |
av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
|
491 |
ap->standard); |
492 |
return AVERROR(EIO);
|
493 |
} |
494 |
} |
495 |
|
496 |
if (ap->time_base.num && ap->time_base.den) {
|
497 |
av_log(s1, AV_LOG_DEBUG, "Setting time per frame to %d/%d\n",
|
498 |
ap->time_base.num, ap->time_base.den); |
499 |
tpf->numerator = ap->time_base.num; |
500 |
tpf->denominator = ap->time_base.den; |
501 |
if (ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) { |
502 |
av_log(s1, AV_LOG_ERROR, |
503 |
"ioctl set time per frame(%d/%d) failed\n",
|
504 |
ap->time_base.num, ap->time_base.den); |
505 |
return AVERROR(EIO);
|
506 |
} |
507 |
|
508 |
if (ap->time_base.den != tpf->denominator ||
|
509 |
ap->time_base.num != tpf->numerator) { |
510 |
av_log(s1, AV_LOG_INFO, |
511 |
"The driver changed the time per frame from %d/%d to %d/%d\n",
|
512 |
ap->time_base.num, ap->time_base.den, |
513 |
tpf->numerator, tpf->denominator); |
514 |
} |
515 |
} else {
|
516 |
/* if timebase value is not set in ap, read the timebase value from the driver */
|
517 |
if (ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) { |
518 |
av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", strerror(errno));
|
519 |
return AVERROR(errno);
|
520 |
} |
521 |
} |
522 |
ap->time_base.num = tpf->numerator; |
523 |
ap->time_base.den = tpf->denominator; |
524 |
|
525 |
return 0; |
526 |
} |
527 |
|
528 |
static uint32_t device_try_init(AVFormatContext *s1,
|
529 |
const AVFormatParameters *ap,
|
530 |
int *width,
|
531 |
int *height,
|
532 |
enum CodecID *codec_id)
|
533 |
{ |
534 |
uint32_t desired_format = fmt_ff2v4l(ap->pix_fmt, s1->video_codec_id); |
535 |
|
536 |
if (desired_format == 0 || |
537 |
device_init(s1, width, height, desired_format) < 0) {
|
538 |
int i;
|
539 |
|
540 |
desired_format = 0;
|
541 |
for (i = 0; i<FF_ARRAY_ELEMS(fmt_conversion_table); i++) { |
542 |
if (s1->video_codec_id == CODEC_ID_NONE ||
|
543 |
fmt_conversion_table[i].codec_id == s1->video_codec_id) { |
544 |
desired_format = fmt_conversion_table[i].v4l2_fmt; |
545 |
if (device_init(s1, width, height, desired_format) >= 0) { |
546 |
break;
|
547 |
} |
548 |
desired_format = 0;
|
549 |
} |
550 |
} |
551 |
} |
552 |
if (desired_format != 0) { |
553 |
*codec_id = fmt_v4l2codec(desired_format); |
554 |
assert(*codec_id != CODEC_ID_NONE); |
555 |
} |
556 |
|
557 |
return desired_format;
|
558 |
} |
559 |
|
560 |
static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
561 |
{ |
562 |
struct video_data *s = s1->priv_data;
|
563 |
AVStream *st; |
564 |
int res;
|
565 |
uint32_t desired_format, capabilities; |
566 |
enum CodecID codec_id;
|
567 |
|
568 |
st = av_new_stream(s1, 0);
|
569 |
if (!st) {
|
570 |
return AVERROR(ENOMEM);
|
571 |
} |
572 |
av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ |
573 |
|
574 |
s->width = ap->width; |
575 |
s->height = ap->height; |
576 |
|
577 |
capabilities = 0;
|
578 |
s->fd = device_open(s1, &capabilities); |
579 |
if (s->fd < 0) { |
580 |
return AVERROR(EIO);
|
581 |
} |
582 |
av_log(s1, AV_LOG_VERBOSE, "[%d]Capabilities: %x\n", s->fd, capabilities);
|
583 |
|
584 |
if (!s->width && !s->height) {
|
585 |
struct v4l2_format fmt;
|
586 |
|
587 |
av_log(s1, AV_LOG_VERBOSE, "Querying the device for the current frame size\n");
|
588 |
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
589 |
if (ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) { |
590 |
av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", strerror(errno));
|
591 |
return AVERROR(errno);
|
592 |
} |
593 |
s->width = fmt.fmt.pix.width; |
594 |
s->height = fmt.fmt.pix.height; |
595 |
av_log(s1, AV_LOG_VERBOSE, "Setting frame size to %dx%d\n", s->width, s->height);
|
596 |
} |
597 |
|
598 |
desired_format = device_try_init(s1, ap, &s->width, &s->height, &codec_id); |
599 |
if (desired_format == 0) { |
600 |
av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
|
601 |
"codec_id %d, pix_fmt %d.\n", s1->video_codec_id, ap->pix_fmt);
|
602 |
close(s->fd); |
603 |
|
604 |
return AVERROR(EIO);
|
605 |
} |
606 |
if (av_image_check_size(s->width, s->height, 0, s1) < 0) |
607 |
return AVERROR(EINVAL);
|
608 |
s->frame_format = desired_format; |
609 |
|
610 |
if (v4l2_set_parameters(s1, ap) < 0) |
611 |
return AVERROR(EIO);
|
612 |
|
613 |
st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id); |
614 |
s->frame_size = avpicture_get_size(st->codec->pix_fmt, s->width, s->height); |
615 |
if (capabilities & V4L2_CAP_STREAMING) {
|
616 |
s->io_method = io_mmap; |
617 |
res = mmap_init(s1); |
618 |
if (res == 0) { |
619 |
res = mmap_start(s1); |
620 |
} |
621 |
} else {
|
622 |
s->io_method = io_read; |
623 |
res = read_init(s1); |
624 |
} |
625 |
if (res < 0) { |
626 |
close(s->fd); |
627 |
|
628 |
return AVERROR(EIO);
|
629 |
} |
630 |
s->top_field_first = first_field(s->fd); |
631 |
|
632 |
st->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
633 |
st->codec->codec_id = codec_id; |
634 |
st->codec->width = s->width; |
635 |
st->codec->height = s->height; |
636 |
st->codec->time_base.den = ap->time_base.den; |
637 |
st->codec->time_base.num = ap->time_base.num; |
638 |
st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8; |
639 |
|
640 |
return 0; |
641 |
} |
642 |
|
643 |
static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt) |
644 |
{ |
645 |
struct video_data *s = s1->priv_data;
|
646 |
int res;
|
647 |
|
648 |
if (s->io_method == io_mmap) {
|
649 |
av_init_packet(pkt); |
650 |
res = mmap_read_frame(s1, pkt); |
651 |
} else if (s->io_method == io_read) { |
652 |
if (av_new_packet(pkt, s->frame_size) < 0) |
653 |
return AVERROR(EIO);
|
654 |
|
655 |
res = read_frame(s1, pkt); |
656 |
} else {
|
657 |
return AVERROR(EIO);
|
658 |
} |
659 |
if (res < 0) { |
660 |
return res;
|
661 |
} |
662 |
|
663 |
if (s1->streams[0]->codec->coded_frame) { |
664 |
s1->streams[0]->codec->coded_frame->interlaced_frame = 1; |
665 |
s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first;
|
666 |
} |
667 |
|
668 |
return pkt->size;
|
669 |
} |
670 |
|
671 |
static int v4l2_read_close(AVFormatContext *s1) |
672 |
{ |
673 |
struct video_data *s = s1->priv_data;
|
674 |
|
675 |
if (s->io_method == io_mmap) {
|
676 |
mmap_close(s); |
677 |
} |
678 |
|
679 |
close(s->fd); |
680 |
return 0; |
681 |
} |
682 |
|
683 |
AVInputFormat ff_v4l2_demuxer = { |
684 |
"video4linux2",
|
685 |
NULL_IF_CONFIG_SMALL("Video4Linux2 device grab"),
|
686 |
sizeof(struct video_data), |
687 |
NULL,
|
688 |
v4l2_read_header, |
689 |
v4l2_read_packet, |
690 |
v4l2_read_close, |
691 |
.flags = AVFMT_NOFILE, |
692 |
}; |