annotate v4l2.c @ 1960:c0289552590f libavformat

Change the vhook code to send real timestamps to the filters instead of the current time of day, which is useless, and which the filters could just as easily query for themselves. patch by Bobby Bingham, uhmmmm gmail com
author diego
date Thu, 29 Mar 2007 05:24:35 +0000
parents 62792a60f740
children 0bb1bfbaa031
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
1 /*
547675092e98 video4linux2 input support
diego
parents:
diff changeset
2 * Video4Linux2 grab interface
547675092e98 video4linux2 input support
diego
parents:
diff changeset
3 * Copyright (c) 2000,2001 Fabrice Bellard.
547675092e98 video4linux2 input support
diego
parents:
diff changeset
4 * Copyright (c) 2006 Luca Abeni.
547675092e98 video4linux2 input support
diego
parents:
diff changeset
5 *
547675092e98 video4linux2 input support
diego
parents:
diff changeset
6 * Part of this file is based on the V4L2 video capture example
547675092e98 video4linux2 input support
diego
parents:
diff changeset
7 * (http://v4l2spec.bytesex.org/v4l2spec/capture.c)
547675092e98 video4linux2 input support
diego
parents:
diff changeset
8 *
547675092e98 video4linux2 input support
diego
parents:
diff changeset
9 * Thanks to Michael Niedermayer for providing the mapping between
547675092e98 video4linux2 input support
diego
parents:
diff changeset
10 * V4L2_PIX_FMT_* and PIX_FMT_*
547675092e98 video4linux2 input support
diego
parents:
diff changeset
11 *
547675092e98 video4linux2 input support
diego
parents:
diff changeset
12 *
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1169
diff changeset
13 * This file is part of FFmpeg.
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1169
diff changeset
14 *
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1169
diff changeset
15 * FFmpeg is free software; you can redistribute it and/or
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
16 * modify it under the terms of the GNU Lesser General Public
547675092e98 video4linux2 input support
diego
parents:
diff changeset
17 * License as published by the Free Software Foundation; either
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1169
diff changeset
18 * version 2.1 of the License, or (at your option) any later version.
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
19 *
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1169
diff changeset
20 * FFmpeg is distributed in the hope that it will be useful,
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
547675092e98 video4linux2 input support
diego
parents:
diff changeset
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
547675092e98 video4linux2 input support
diego
parents:
diff changeset
23 * Lesser General Public License for more details.
547675092e98 video4linux2 input support
diego
parents:
diff changeset
24 *
547675092e98 video4linux2 input support
diego
parents:
diff changeset
25 * You should have received a copy of the GNU Lesser General Public
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1169
diff changeset
26 * License along with FFmpeg; if not, write to the Free Software
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
547675092e98 video4linux2 input support
diego
parents:
diff changeset
28 */
547675092e98 video4linux2 input support
diego
parents:
diff changeset
29 #include "avformat.h"
547675092e98 video4linux2 input support
diego
parents:
diff changeset
30 #include <unistd.h>
547675092e98 video4linux2 input support
diego
parents:
diff changeset
31 #include <fcntl.h>
547675092e98 video4linux2 input support
diego
parents:
diff changeset
32 #include <sys/ioctl.h>
547675092e98 video4linux2 input support
diego
parents:
diff changeset
33 #include <sys/mman.h>
547675092e98 video4linux2 input support
diego
parents:
diff changeset
34 #include <sys/time.h>
1100
d4793a811695 Include the correct video4linux2 header
lucabe
parents: 1013
diff changeset
35 #include <asm/types.h>
d4793a811695 Include the correct video4linux2 header
lucabe
parents: 1013
diff changeset
36 #include <linux/videodev2.h>
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
37 #include <time.h>
547675092e98 video4linux2 input support
diego
parents:
diff changeset
38
547675092e98 video4linux2 input support
diego
parents:
diff changeset
39 static const int desired_video_buffers = 256;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
40
547675092e98 video4linux2 input support
diego
parents:
diff changeset
41 enum io_method {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
42 io_read,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
43 io_mmap,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
44 io_userptr
547675092e98 video4linux2 input support
diego
parents:
diff changeset
45 };
547675092e98 video4linux2 input support
diego
parents:
diff changeset
46
547675092e98 video4linux2 input support
diego
parents:
diff changeset
47 struct video_data {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
48 int fd;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
49 int frame_format; /* V4L2_PIX_FMT_* */
547675092e98 video4linux2 input support
diego
parents:
diff changeset
50 enum io_method io_method;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
51 int width, height;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
52 int frame_rate;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
53 int frame_rate_base;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
54 int frame_size;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
55 int top_field_first;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
56
547675092e98 video4linux2 input support
diego
parents:
diff changeset
57 int buffers;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
58 void **buf_start;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
59 unsigned int *buf_len;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
60 };
547675092e98 video4linux2 input support
diego
parents:
diff changeset
61
1793
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
62 struct buff_data {
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
63 int index;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
64 int fd;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
65 };
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
66
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
67 struct fmt_map {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
68 enum PixelFormat ff_fmt;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
69 int32_t v4l2_fmt;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
70 };
547675092e98 video4linux2 input support
diego
parents:
diff changeset
71
547675092e98 video4linux2 input support
diego
parents:
diff changeset
72 static struct fmt_map fmt_conversion_table[] = {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
73 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
74 .ff_fmt = PIX_FMT_YUV420P,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
75 .v4l2_fmt = V4L2_PIX_FMT_YUV420,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
76 },
547675092e98 video4linux2 input support
diego
parents:
diff changeset
77 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
78 .ff_fmt = PIX_FMT_YUV422P,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
79 .v4l2_fmt = V4L2_PIX_FMT_YUV422P,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
80 },
547675092e98 video4linux2 input support
diego
parents:
diff changeset
81 {
1760
8cba5672faa4 Replace deprecated PIX_FMT names by the newer variants.
diego
parents: 1556
diff changeset
82 .ff_fmt = PIX_FMT_YUYV422,
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
83 .v4l2_fmt = V4L2_PIX_FMT_YUYV,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
84 },
547675092e98 video4linux2 input support
diego
parents:
diff changeset
85 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
86 .ff_fmt = PIX_FMT_UYVY422,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
87 .v4l2_fmt = V4L2_PIX_FMT_UYVY,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
88 },
547675092e98 video4linux2 input support
diego
parents:
diff changeset
89 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
90 .ff_fmt = PIX_FMT_YUV411P,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
91 .v4l2_fmt = V4L2_PIX_FMT_YUV411P,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
92 },
547675092e98 video4linux2 input support
diego
parents:
diff changeset
93 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
94 .ff_fmt = PIX_FMT_YUV410P,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
95 .v4l2_fmt = V4L2_PIX_FMT_YUV410,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
96 },
547675092e98 video4linux2 input support
diego
parents:
diff changeset
97 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
98 .ff_fmt = PIX_FMT_BGR24,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
99 .v4l2_fmt = V4L2_PIX_FMT_BGR24,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
100 },
547675092e98 video4linux2 input support
diego
parents:
diff changeset
101 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
102 .ff_fmt = PIX_FMT_RGB24,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
103 .v4l2_fmt = V4L2_PIX_FMT_RGB24,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
104 },
547675092e98 video4linux2 input support
diego
parents:
diff changeset
105 /*
547675092e98 video4linux2 input support
diego
parents:
diff changeset
106 {
1760
8cba5672faa4 Replace deprecated PIX_FMT names by the newer variants.
diego
parents: 1556
diff changeset
107 .ff_fmt = PIX_FMT_RGB32,
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
108 .v4l2_fmt = V4L2_PIX_FMT_BGR32,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
109 },
547675092e98 video4linux2 input support
diego
parents:
diff changeset
110 */
547675092e98 video4linux2 input support
diego
parents:
diff changeset
111 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
112 .ff_fmt = PIX_FMT_GRAY8,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
113 .v4l2_fmt = V4L2_PIX_FMT_GREY,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
114 },
547675092e98 video4linux2 input support
diego
parents:
diff changeset
115 };
547675092e98 video4linux2 input support
diego
parents:
diff changeset
116
1795
62792a60f740 implement new grabbing interface, as described here:
gpoirier
parents: 1793
diff changeset
117 static int device_open(AVFormatContext *ctx, uint32_t *capabilities)
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
118 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
119 struct v4l2_capability cap;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
120 int fd;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
121 int res;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
122
1795
62792a60f740 implement new grabbing interface, as described here:
gpoirier
parents: 1793
diff changeset
123 fd = open(ctx->filename, O_RDWR /*| O_NONBLOCK*/, 0);
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
124 if (fd < 0) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
125 av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
1795
62792a60f740 implement new grabbing interface, as described here:
gpoirier
parents: 1793
diff changeset
126 ctx->filename, strerror(errno));
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
127
547675092e98 video4linux2 input support
diego
parents:
diff changeset
128 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
129 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
130
547675092e98 video4linux2 input support
diego
parents:
diff changeset
131 res = ioctl(fd, VIDIOC_QUERYCAP, &cap);
973
136f654dfc03 print a hint when trying V4L2 on V4L device
alex
parents: 921
diff changeset
132 // ENOIOCTLCMD definition only availble on __KERNEL__
136f654dfc03 print a hint when trying V4L2 on V4L device
alex
parents: 921
diff changeset
133 if (res < 0 && errno == 515)
136f654dfc03 print a hint when trying V4L2 on V4L device
alex
parents: 921
diff changeset
134 {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
135 av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n");
974
e0cfc88ad93a Error path fix: close the video device on failure
lucabe
parents: 973
diff changeset
136 close(fd);
973
136f654dfc03 print a hint when trying V4L2 on V4L device
alex
parents: 921
diff changeset
137
136f654dfc03 print a hint when trying V4L2 on V4L device
alex
parents: 921
diff changeset
138 return -1;
136f654dfc03 print a hint when trying V4L2 on V4L device
alex
parents: 921
diff changeset
139 }
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
140 if (res < 0) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
141 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
142 strerror(errno));
974
e0cfc88ad93a Error path fix: close the video device on failure
lucabe
parents: 973
diff changeset
143 close(fd);
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
144
547675092e98 video4linux2 input support
diego
parents:
diff changeset
145 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
146 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
147 if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
148 av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n");
974
e0cfc88ad93a Error path fix: close the video device on failure
lucabe
parents: 973
diff changeset
149 close(fd);
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
150
547675092e98 video4linux2 input support
diego
parents:
diff changeset
151 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
152 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
153 *capabilities = cap.capabilities;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
154
547675092e98 video4linux2 input support
diego
parents:
diff changeset
155 return fd;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
156 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
157
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
158 static int device_init(AVFormatContext *ctx, int *width, int *height, int pix_fmt)
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
159 {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
160 struct video_data *s = ctx->priv_data;
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
161 int fd = s->fd;
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
162 struct v4l2_format fmt;
975
36a69fbabcfb Add support for drivers that can change the capture size on VIDIOC_S_FMT
lucabe
parents: 974
diff changeset
163 int res;
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
164
547675092e98 video4linux2 input support
diego
parents:
diff changeset
165 memset(&fmt, 0, sizeof(struct v4l2_format));
547675092e98 video4linux2 input support
diego
parents:
diff changeset
166 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
975
36a69fbabcfb Add support for drivers that can change the capture size on VIDIOC_S_FMT
lucabe
parents: 974
diff changeset
167 fmt.fmt.pix.width = *width;
36a69fbabcfb Add support for drivers that can change the capture size on VIDIOC_S_FMT
lucabe
parents: 974
diff changeset
168 fmt.fmt.pix.height = *height;
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
169 fmt.fmt.pix.pixelformat = pix_fmt;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
170 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
975
36a69fbabcfb Add support for drivers that can change the capture size on VIDIOC_S_FMT
lucabe
parents: 974
diff changeset
171 res = ioctl(fd, VIDIOC_S_FMT, &fmt);
36a69fbabcfb Add support for drivers that can change the capture size on VIDIOC_S_FMT
lucabe
parents: 974
diff changeset
172 if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
173 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);
975
36a69fbabcfb Add support for drivers that can change the capture size on VIDIOC_S_FMT
lucabe
parents: 974
diff changeset
174 *width = fmt.fmt.pix.width;
36a69fbabcfb Add support for drivers that can change the capture size on VIDIOC_S_FMT
lucabe
parents: 974
diff changeset
175 *height = fmt.fmt.pix.height;
36a69fbabcfb Add support for drivers that can change the capture size on VIDIOC_S_FMT
lucabe
parents: 974
diff changeset
176 }
36a69fbabcfb Add support for drivers that can change the capture size on VIDIOC_S_FMT
lucabe
parents: 974
diff changeset
177
36a69fbabcfb Add support for drivers that can change the capture size on VIDIOC_S_FMT
lucabe
parents: 974
diff changeset
178 return res;
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
179 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
180
547675092e98 video4linux2 input support
diego
parents:
diff changeset
181 static int first_field(int fd)
547675092e98 video4linux2 input support
diego
parents:
diff changeset
182 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
183 int res;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
184 v4l2_std_id std;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
185
547675092e98 video4linux2 input support
diego
parents:
diff changeset
186 res = ioctl(fd, VIDIOC_G_STD, &std);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
187 if (res < 0) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
188 return 0;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
189 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
190 if (std & V4L2_STD_NTSC) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
191 return 0;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
192 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
193
547675092e98 video4linux2 input support
diego
parents:
diff changeset
194 return 1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
195 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
196
547675092e98 video4linux2 input support
diego
parents:
diff changeset
197 static uint32_t fmt_ff2v4l(enum PixelFormat pix_fmt)
547675092e98 video4linux2 input support
diego
parents:
diff changeset
198 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
199 int i;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
200
547675092e98 video4linux2 input support
diego
parents:
diff changeset
201 for (i = 0; i < sizeof(fmt_conversion_table) / sizeof(struct fmt_map); i++) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
202 if (fmt_conversion_table[i].ff_fmt == pix_fmt) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
203 return fmt_conversion_table[i].v4l2_fmt;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
204 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
205 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
206
547675092e98 video4linux2 input support
diego
parents:
diff changeset
207 return 0;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
208 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
209
547675092e98 video4linux2 input support
diego
parents:
diff changeset
210 static enum PixelFormat fmt_v4l2ff(uint32_t pix_fmt)
547675092e98 video4linux2 input support
diego
parents:
diff changeset
211 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
212 int i;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
213
547675092e98 video4linux2 input support
diego
parents:
diff changeset
214 for (i = 0; i < sizeof(fmt_conversion_table) / sizeof(struct fmt_map); i++) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
215 if (fmt_conversion_table[i].v4l2_fmt == pix_fmt) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
216 return fmt_conversion_table[i].ff_fmt;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
217 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
218 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
219
547675092e98 video4linux2 input support
diego
parents:
diff changeset
220 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
221 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
222
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
223 static int mmap_init(AVFormatContext *ctx)
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
224 {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
225 struct video_data *s = ctx->priv_data;
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
226 struct v4l2_requestbuffers req;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
227 int i, res;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
228
547675092e98 video4linux2 input support
diego
parents:
diff changeset
229 memset(&req, 0, sizeof(struct v4l2_requestbuffers));
547675092e98 video4linux2 input support
diego
parents:
diff changeset
230 req.count = desired_video_buffers;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
231 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
232 req.memory = V4L2_MEMORY_MMAP;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
233 res = ioctl (s->fd, VIDIOC_REQBUFS, &req);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
234 if (res < 0) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
235 if (errno == EINVAL) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
236 av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
237 } else {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
238 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
239 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
240
547675092e98 video4linux2 input support
diego
parents:
diff changeset
241 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
242 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
243
547675092e98 video4linux2 input support
diego
parents:
diff changeset
244 if (req.count < 2) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
245 av_log(ctx, AV_LOG_ERROR, "Insufficient buffer memory\n");
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
246
547675092e98 video4linux2 input support
diego
parents:
diff changeset
247 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
248 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
249 s->buffers = req.count;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
250 s->buf_start = av_malloc(sizeof(void *) * s->buffers);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
251 if (s->buf_start == NULL) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
252 av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
253
547675092e98 video4linux2 input support
diego
parents:
diff changeset
254 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
255 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
256 s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
257 if (s->buf_len == NULL) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
258 av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
259 av_free(s->buf_start);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
260
547675092e98 video4linux2 input support
diego
parents:
diff changeset
261 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
262 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
263
547675092e98 video4linux2 input support
diego
parents:
diff changeset
264 for (i = 0; i < req.count; i++) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
265 struct v4l2_buffer buf;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
266
547675092e98 video4linux2 input support
diego
parents:
diff changeset
267 memset(&buf, 0, sizeof(struct v4l2_buffer));
547675092e98 video4linux2 input support
diego
parents:
diff changeset
268 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
269 buf.memory = V4L2_MEMORY_MMAP;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
270 buf.index = i;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
271 res = ioctl (s->fd, VIDIOC_QUERYBUF, &buf);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
272 if (res < 0) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
273 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
274
547675092e98 video4linux2 input support
diego
parents:
diff changeset
275 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
276 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
277
547675092e98 video4linux2 input support
diego
parents:
diff changeset
278 s->buf_len[i] = buf.length;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
279 if (s->buf_len[i] < s->frame_size) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
280 av_log(ctx, AV_LOG_ERROR, "Buffer len [%d] = %d != %d\n", i, s->buf_len[i], s->frame_size);
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
281
547675092e98 video4linux2 input support
diego
parents:
diff changeset
282 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
283 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
284 s->buf_start[i] = mmap (NULL, buf.length,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
285 PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
286 if (s->buf_start[i] == MAP_FAILED) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
287 av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
288
547675092e98 video4linux2 input support
diego
parents:
diff changeset
289 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
290 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
291 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
292
547675092e98 video4linux2 input support
diego
parents:
diff changeset
293 return 0;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
294 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
295
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
296 static int read_init(AVFormatContext *ctx)
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
297 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
298 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
299 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
300
1793
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
301 static void mmap_release_buffer(AVPacket *pkt)
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
302 {
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
303 struct v4l2_buffer buf;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
304 int res, fd;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
305 struct buff_data *buf_descriptor = pkt->priv;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
306
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
307 memset(&buf, 0, sizeof(struct v4l2_buffer));
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
308 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
309 buf.memory = V4L2_MEMORY_MMAP;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
310 buf.index = buf_descriptor->index;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
311 fd = buf_descriptor->fd;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
312 av_free(buf_descriptor);
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
313
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
314 res = ioctl (fd, VIDIOC_QBUF, &buf);
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
315 if (res < 0) {
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
316 av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
317 }
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
318 pkt->data = NULL;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
319 pkt->size = 0;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
320 }
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
321
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
322 static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
323 {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
324 struct video_data *s = ctx->priv_data;
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
325 struct v4l2_buffer buf;
1793
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
326 struct buff_data *buf_descriptor;
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
327 int res;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
328
547675092e98 video4linux2 input support
diego
parents:
diff changeset
329 memset(&buf, 0, sizeof(struct v4l2_buffer));
547675092e98 video4linux2 input support
diego
parents:
diff changeset
330 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
331 buf.memory = V4L2_MEMORY_MMAP;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
332
547675092e98 video4linux2 input support
diego
parents:
diff changeset
333 /* FIXME: Some special treatment might be needed in case of loss of signal... */
547675092e98 video4linux2 input support
diego
parents:
diff changeset
334 while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 &&
547675092e98 video4linux2 input support
diego
parents:
diff changeset
335 ((errno == EAGAIN) || (errno == EINTR)));
547675092e98 video4linux2 input support
diego
parents:
diff changeset
336 if (res < 0) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
337 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", strerror(errno));
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
338
547675092e98 video4linux2 input support
diego
parents:
diff changeset
339 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
340 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
341 assert (buf.index < s->buffers);
1407
fb4bf3858f77 Make read_packet fail is the v4l2 driver returns an unexpected frame size
lucabe
parents: 1358
diff changeset
342 if (buf.bytesused != s->frame_size) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
343 av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size);
1407
fb4bf3858f77 Make read_packet fail is the v4l2 driver returns an unexpected frame size
lucabe
parents: 1358
diff changeset
344
fb4bf3858f77 Make read_packet fail is the v4l2 driver returns an unexpected frame size
lucabe
parents: 1358
diff changeset
345 return -1;
fb4bf3858f77 Make read_packet fail is the v4l2 driver returns an unexpected frame size
lucabe
parents: 1358
diff changeset
346 }
fb4bf3858f77 Make read_packet fail is the v4l2 driver returns an unexpected frame size
lucabe
parents: 1358
diff changeset
347
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
348 /* Image is at s->buff_start[buf.index] */
1793
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
349 pkt->data= s->buf_start[buf.index];
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
350 pkt->size = buf.bytesused;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
351 pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
352 pkt->destruct = mmap_release_buffer;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
353 buf_descriptor = av_malloc(sizeof(struct buff_data));
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
354 if (buf_descriptor == NULL) {
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
355 /* Something went wrong... Since av_malloc() failed, we cannot even
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
356 * allocate a buffer for memcopying into it
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
357 */
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
358 av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
359 res = ioctl (s->fd, VIDIOC_QBUF, &buf);
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
360
547675092e98 video4linux2 input support
diego
parents:
diff changeset
361 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
362 }
1793
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
363 buf_descriptor->fd = s->fd;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
364 buf_descriptor->index = buf.index;
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
365 pkt->priv = buf_descriptor;
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
366
547675092e98 video4linux2 input support
diego
parents:
diff changeset
367 return s->buf_len[buf.index];
547675092e98 video4linux2 input support
diego
parents:
diff changeset
368 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
369
1793
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
370 static int read_frame(AVFormatContext *ctx, AVPacket *pkt)
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
371 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
372 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
373 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
374
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
375 static int mmap_start(AVFormatContext *ctx)
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
376 {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
377 struct video_data *s = ctx->priv_data;
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
378 enum v4l2_buf_type type;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
379 int i, res;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
380
547675092e98 video4linux2 input support
diego
parents:
diff changeset
381 for (i = 0; i < s->buffers; i++) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
382 struct v4l2_buffer buf;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
383
547675092e98 video4linux2 input support
diego
parents:
diff changeset
384 memset(&buf, 0, sizeof(struct v4l2_buffer));
547675092e98 video4linux2 input support
diego
parents:
diff changeset
385 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
386 buf.memory = V4L2_MEMORY_MMAP;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
387 buf.index = i;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
388
547675092e98 video4linux2 input support
diego
parents:
diff changeset
389 res = ioctl (s->fd, VIDIOC_QBUF, &buf);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
390 if (res < 0) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
391 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
392
547675092e98 video4linux2 input support
diego
parents:
diff changeset
393 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
394 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
395 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
396
547675092e98 video4linux2 input support
diego
parents:
diff changeset
397 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
398 res = ioctl (s->fd, VIDIOC_STREAMON, &type);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
399 if (res < 0) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
400 av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno));
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
401
547675092e98 video4linux2 input support
diego
parents:
diff changeset
402 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
403 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
404
547675092e98 video4linux2 input support
diego
parents:
diff changeset
405 return 0;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
406 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
407
547675092e98 video4linux2 input support
diego
parents:
diff changeset
408 static void mmap_close(struct video_data *s)
547675092e98 video4linux2 input support
diego
parents:
diff changeset
409 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
410 enum v4l2_buf_type type;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
411 int i;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
412
547675092e98 video4linux2 input support
diego
parents:
diff changeset
413 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
414 /* We do not check for the result, because we could
547675092e98 video4linux2 input support
diego
parents:
diff changeset
415 * not do anything about it anyway...
547675092e98 video4linux2 input support
diego
parents:
diff changeset
416 */
547675092e98 video4linux2 input support
diego
parents:
diff changeset
417 ioctl(s->fd, VIDIOC_STREAMOFF, &type);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
418 for (i = 0; i < s->buffers; i++) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
419 munmap(s->buf_start[i], s->buf_len[i]);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
420 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
421 av_free(s->buf_start);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
422 av_free(s->buf_len);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
423 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
424
547675092e98 video4linux2 input support
diego
parents:
diff changeset
425 static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
547675092e98 video4linux2 input support
diego
parents:
diff changeset
426 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
427 struct video_data *s = s1->priv_data;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
428 AVStream *st;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
429 int width, height;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
430 int res, frame_rate, frame_rate_base;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
431 uint32_t desired_format, capabilities;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
432
1003
2d57ce58f576 simplify AVFormatParameters NULL checks
michael
parents: 975
diff changeset
433 if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
434 av_log(s1, AV_LOG_ERROR, "Missing/Wrong parameters\n");
547675092e98 video4linux2 input support
diego
parents:
diff changeset
435
547675092e98 video4linux2 input support
diego
parents:
diff changeset
436 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
437 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
438
547675092e98 video4linux2 input support
diego
parents:
diff changeset
439 width = ap->width;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
440 height = ap->height;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
441 frame_rate = ap->time_base.den;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
442 frame_rate_base = ap->time_base.num;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
443
547675092e98 video4linux2 input support
diego
parents:
diff changeset
444 if((unsigned)width > 32767 || (unsigned)height > 32767) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
445 av_log(s1, AV_LOG_ERROR, "Wrong size %dx%d\n", width, height);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
446
547675092e98 video4linux2 input support
diego
parents:
diff changeset
447 return -1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
448 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
449
547675092e98 video4linux2 input support
diego
parents:
diff changeset
450 st = av_new_stream(s1, 0);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
451 if (!st) {
1787
eb16c64144ee This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents: 1780
diff changeset
452 return AVERROR(ENOMEM);
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
453 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
454 av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
547675092e98 video4linux2 input support
diego
parents:
diff changeset
455
547675092e98 video4linux2 input support
diego
parents:
diff changeset
456 s->width = width;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
457 s->height = height;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
458 s->frame_rate = frame_rate;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
459 s->frame_rate_base = frame_rate_base;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
460
547675092e98 video4linux2 input support
diego
parents:
diff changeset
461 capabilities = 0;
1795
62792a60f740 implement new grabbing interface, as described here:
gpoirier
parents: 1793
diff changeset
462 s->fd = device_open(s1, &capabilities);
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
463 if (s->fd < 0) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
464 av_free(st);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
465
547675092e98 video4linux2 input support
diego
parents:
diff changeset
466 return AVERROR_IO;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
467 }
1013
4abfc175a5d7 Do not be too verbose
lucabe
parents: 1003
diff changeset
468 av_log(s1, AV_LOG_INFO, "[%d]Capabilities: %x\n", s->fd, capabilities);
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
469
547675092e98 video4linux2 input support
diego
parents:
diff changeset
470 desired_format = fmt_ff2v4l(ap->pix_fmt);
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
471 if (desired_format == 0 || (device_init(s1, &width, &height, desired_format) < 0)) {
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
472 int i, done;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
473
547675092e98 video4linux2 input support
diego
parents:
diff changeset
474 done = 0; i = 0;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
475 while (!done) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
476 desired_format = fmt_conversion_table[i].v4l2_fmt;
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
477 if (device_init(s1, &width, &height, desired_format) < 0) {
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
478 desired_format = 0;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
479 i++;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
480 } else {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
481 done = 1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
482 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
483 if (i == sizeof(fmt_conversion_table) / sizeof(struct fmt_map)) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
484 done = 1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
485 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
486 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
487 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
488 if (desired_format == 0) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
489 av_log(s1, AV_LOG_ERROR, "Cannot find a proper format.\n");
547675092e98 video4linux2 input support
diego
parents:
diff changeset
490 close(s->fd);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
491 av_free(st);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
492
547675092e98 video4linux2 input support
diego
parents:
diff changeset
493 return AVERROR_IO;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
494 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
495 s->frame_format = desired_format;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
496
547675092e98 video4linux2 input support
diego
parents:
diff changeset
497 st->codec->pix_fmt = fmt_v4l2ff(desired_format);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
498 s->frame_size = avpicture_get_size(st->codec->pix_fmt, width, height);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
499 if (capabilities & V4L2_CAP_STREAMING) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
500 s->io_method = io_mmap;
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
501 res = mmap_init(s1);
1117
1291569071c6 Fix segfault
lucabe
parents: 1100
diff changeset
502 if (res == 0) {
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
503 res = mmap_start(s1);
1117
1291569071c6 Fix segfault
lucabe
parents: 1100
diff changeset
504 }
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
505 } else {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
506 s->io_method = io_read;
1780
5e6a9b3a9698 Pass a proper context to av_log()
lucabe
parents: 1760
diff changeset
507 res = read_init(s1);
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
508 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
509 if (res < 0) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
510 close(s->fd);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
511 av_free(st);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
512
547675092e98 video4linux2 input support
diego
parents:
diff changeset
513 return AVERROR_IO;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
514 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
515 s->top_field_first = first_field(s->fd);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
516
547675092e98 video4linux2 input support
diego
parents:
diff changeset
517 st->codec->codec_type = CODEC_TYPE_VIDEO;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
518 st->codec->codec_id = CODEC_ID_RAWVIDEO;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
519 st->codec->width = width;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
520 st->codec->height = height;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
521 st->codec->time_base.den = frame_rate;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
522 st->codec->time_base.num = frame_rate_base;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
523 st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
524
547675092e98 video4linux2 input support
diego
parents:
diff changeset
525 return 0;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
526 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
527
547675092e98 video4linux2 input support
diego
parents:
diff changeset
528 static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt)
547675092e98 video4linux2 input support
diego
parents:
diff changeset
529 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
530 struct video_data *s = s1->priv_data;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
531 int res;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
532
1793
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
533 if (s->io_method == io_mmap) {
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
534 av_init_packet(pkt);
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
535 res = mmap_read_frame(s1, pkt);
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
536 } else if (s->io_method == io_read) {
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
537 if (av_new_packet(pkt, s->frame_size) < 0)
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
538 return AVERROR_IO;
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
539
1793
951d219ab67b Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
lucabe
parents: 1787
diff changeset
540 res = read_frame(s1, pkt);
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
541 } else {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
542 return AVERROR_IO;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
543 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
544 if (res < 0) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
545 return AVERROR_IO;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
546 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
547
547675092e98 video4linux2 input support
diego
parents:
diff changeset
548 if (s1->streams[0]->codec->coded_frame) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
549 s1->streams[0]->codec->coded_frame->interlaced_frame = 1;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
550 s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
551 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
552
547675092e98 video4linux2 input support
diego
parents:
diff changeset
553 return s->frame_size;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
554 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
555
547675092e98 video4linux2 input support
diego
parents:
diff changeset
556 static int v4l2_read_close(AVFormatContext *s1)
547675092e98 video4linux2 input support
diego
parents:
diff changeset
557 {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
558 struct video_data *s = s1->priv_data;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
559
547675092e98 video4linux2 input support
diego
parents:
diff changeset
560 if (s->io_method == io_mmap) {
547675092e98 video4linux2 input support
diego
parents:
diff changeset
561 mmap_close(s);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
562 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
563
547675092e98 video4linux2 input support
diego
parents:
diff changeset
564 close(s->fd);
547675092e98 video4linux2 input support
diego
parents:
diff changeset
565 return 0;
547675092e98 video4linux2 input support
diego
parents:
diff changeset
566 }
547675092e98 video4linux2 input support
diego
parents:
diff changeset
567
1169
d18cc9a1fd02 allow individual selection of muxers and demuxers
mru
parents: 1167
diff changeset
568 AVInputFormat v4l2_demuxer = {
921
547675092e98 video4linux2 input support
diego
parents:
diff changeset
569 "video4linux2",
547675092e98 video4linux2 input support
diego
parents:
diff changeset
570 "video grab",
547675092e98 video4linux2 input support
diego
parents:
diff changeset
571 sizeof(struct video_data),
547675092e98 video4linux2 input support
diego
parents:
diff changeset
572 NULL,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
573 v4l2_read_header,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
574 v4l2_read_packet,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
575 v4l2_read_close,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
576 .flags = AVFMT_NOFILE,
547675092e98 video4linux2 input support
diego
parents:
diff changeset
577 };