3 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>
6 * Faculty of Computer Science, Mathematics and Natural Sciences,
7 * Leipzig University of Applied Sciences (HTWK Leipzig)
20 #include <sys/types.h>
23 #include <asm/types.h>
24 #include <linux/videodev2.h>
31 #define CLIP(color) (unsigned char) (((color) > 0xFF) ? \
32 0xff : (((color) < 0) ? 0 : (color)))
34 void convert_v4l_yuyv_to_rgb24(const uint8_t *src
, uint8_t *dest
,
35 int width
, int height
)
37 /* From: Hans de Goede <j.w.r.degoede@hhs.nl> */
40 while(--height
>= 0) {
41 for(j
= 0; j
< width
; j
+= 2) {
44 int u1
= (((u
- 128) << 7) + (u
- 128)) >> 6;
45 int rg
= (((u
- 128) << 1) + (u
- 128) +
46 ((v
- 128) << 2) + ((v
- 128) << 1)) >> 3;
47 int v1
= (((v
- 128) << 1) + (v
- 128)) >> 1;
49 *dest
++ = CLIP(src
[0] + v1
);
50 *dest
++ = CLIP(src
[0] - rg
);
51 *dest
++ = CLIP(src
[0] + u1
);
52 *dest
++ = CLIP(src
[2] + v1
);
53 *dest
++ = CLIP(src
[2] - rg
);
54 *dest
++ = CLIP(src
[2] + u1
);
60 int read_v4l_frame(int fd
, unsigned int nbuffs
,
61 struct v4l_buff
*buffs
,
62 int (*rx_v4l_cb
)(uint8_t *frame
, size_t len
))
65 struct v4l2_buffer buf
;
67 if (unlikely(!buffs
|| !nbuffs
))
70 memset(&buf
, 0, sizeof(buf
));
71 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
72 buf
.memory
= V4L2_MEMORY_MMAP
;
74 ret
= xioctl(fd
, VIDIOC_DQBUF
, &buf
);
81 panic("I/O dequeue error!\n");
85 if (unlikely(buf
.index
>= nbuffs
))
86 panic("I/O overflow error!\n");
88 rc
= rx_v4l_cb(buffs
[buf
.index
].start
, buffs
[buf
.index
].length
);
90 ret
= xioctl(fd
, VIDIOC_QBUF
, &buf
);
92 panic("I/O enqueue error!\n");
97 int open_v4l_device(char *dev
)
105 memset(&st
, 0, sizeof(st
));
106 ret
= stat(dev
, &st
);
108 panic("Cannot identify %s!\n", dev
);
110 if (!S_ISCHR(st
.st_mode
))
111 panic("%s is no device!\n", dev
);
113 fd
= open(dev
, O_RDWR
| O_NONBLOCK
, 0);
115 panic("Cannot open %s!\n", dev
);
120 void close_vl4_device(int fd
)
127 int start_v4l_capturing(int fd
, unsigned int nbuffs
)
131 enum v4l2_buf_type type
;
133 for (i
= 0; i
< nbuffs
; ++i
) {
134 struct v4l2_buffer buf
;
136 memset(&buf
, 0, sizeof(buf
));
137 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
138 buf
.memory
= V4L2_MEMORY_MMAP
;
141 ret
= xioctl(fd
, VIDIOC_QBUF
, &buf
);
143 panic("I/O enqueue error!\n");
146 type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
147 ret
= xioctl(fd
, VIDIOC_STREAMON
, &type
);
149 panic("Cannot start capture!\n");
154 int stop_v4l_capturing(int fd
)
157 enum v4l2_buf_type type
;
159 type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
160 ret
= xioctl(fd
, VIDIOC_STREAMOFF
, &type
);
162 panic("Cannot stop capture!\n");
167 int init_mmap(int fd
, const char *dev
, unsigned int *nbuffs
,
168 struct v4l_buff
**buffs
, int frames
)
171 struct v4l2_requestbuffers setup
;
173 if (unlikely(!dev
|| !nbuffs
|| !buffs
))
176 frames
= 3; /* default */
178 memset(&setup
, 0, sizeof(setup
));
179 setup
.count
= frames
; /* queuelen */
180 setup
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
181 setup
.memory
= V4L2_MEMORY_MMAP
;
183 ret
= xioctl(fd
, VIDIOC_REQBUFS
, &setup
);
186 panic("No mmap support!\n");
188 panic("I/O error!\n");
192 panic("Insufficient buffer memory!\n");
194 (*buffs
) = xzmalloc(setup
.count
* sizeof(**buffs
));
196 for ((*nbuffs
) = 0; (*nbuffs
) < setup
.count
; ++(*nbuffs
)) {
197 struct v4l2_buffer buf
;
199 memset(&buf
, 0, sizeof(buf
));
200 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
201 buf
.memory
= V4L2_MEMORY_MMAP
;
202 buf
.index
= (*nbuffs
);
204 ret
= xioctl(fd
, VIDIOC_QUERYBUF
, &buf
);
206 panic("Cannot query buf!\n");
208 (*buffs
)[(*nbuffs
)].length
= buf
.length
;
209 (*buffs
)[(*nbuffs
)].start
= mmap(NULL
, buf
.length
,
210 PROT_READ
| PROT_WRITE
,
211 MAP_SHARED
, fd
, buf
.m
.offset
);
212 if (MAP_FAILED
== (*buffs
)[(*nbuffs
)].start
)
213 panic("Error on mmap!\n");
219 void set_v4l_ctl_or_die(int fd
, unsigned int id
, int value
)
222 struct v4l2_control control_s
;
223 struct v4l2_queryctrl queryctrl
;
225 memset(&queryctrl
, 0, sizeof(queryctrl
));
228 ret
= xioctl(fd
, VIDIOC_QUERYCTRL
, &queryctrl
);
230 panic("Cannot query cmd id %x!\n", id
);
231 if (queryctrl
.flags
& V4L2_CTRL_FLAG_DISABLED
)
232 panic("Cmd id %x disabled!\n", id
);
233 if (queryctrl
.type
!= V4L2_CTRL_TYPE_BOOLEAN
&&
234 queryctrl
.type
!= V4L2_CTRL_TYPE_INTEGER
&&
235 queryctrl
.type
!= V4L2_CTRL_TYPE_MENU
)
236 panic("Cmd id %x has unsupported query type!\n", id
);
237 if (value
< queryctrl
.minimum
)
238 value
= queryctrl
.minimum
;
239 if (value
> queryctrl
.maximum
)
240 value
= queryctrl
.maximum
;
242 value
= queryctrl
.default_value
;
244 memset(&control_s
, 0, sizeof(control_s
));
246 control_s
.value
= value
;
248 ret
= xioctl(fd
, VIDIOC_S_CTRL
, &control_s
);
250 panic("Cannot set cmd id %x!\n", id
);
253 int init_v4l_device(int fd
, int width
, int height
)
257 struct v4l2_capability cap
;
258 struct v4l2_control control
;
259 struct v4l2_cropcap cropcap
;
260 struct v4l2_crop crop
;
261 struct v4l2_format fmt
;
262 struct v4l2_streamparm fps
;
264 memset(&cap
, 0, sizeof(cap
));
265 ret
= xioctl(fd
, VIDIOC_QUERYCAP
, &cap
);
268 panic("This is no V4L2 device!\n");
270 panic("V4L2 error on device!\n");
273 if ((cap
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
) == 0)
274 panic("This is no video capture device!\n");
276 if ((cap
.capabilities
& V4L2_CAP_STREAMING
) == 0)
277 panic("No streaming support for this device!\n");
279 memset(&cropcap
, 0, sizeof(cropcap
));
280 cropcap
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
282 ret
= xioctl(fd
, VIDIOC_CROPCAP
, &cropcap
);
284 memset(&crop
, 0, sizeof(crop
));
285 crop
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
286 crop
.c
= cropcap
.defrect
;
288 ret
= xioctl(fd
, VIDIOC_S_CROP
, &crop
);
292 /* Cropping not supported. */
299 /* This is for the buggy AMD driver, we need to do this first! */
300 memset(&control
, 0, sizeof(control
));
301 control
.id
= V4L2_CID_CAM_INIT
;
304 ret
= xioctl(fd
, VIDIOC_S_CTRL
, &control
);
306 panic("%s cannot set cam init!\n");
308 /* Aldebaran setting */
309 if (width
== 640 && height
== 480)
310 esid0
= 0x08000000UL
; /*VGA*/
311 else if (width
== 320 && height
== 240)
312 esid0
= 0x04000000UL
; /*QVGA*/
314 panic("Panic over invalid width/height settings!\n");
316 ret
= xioctl(fd
, VIDIOC_S_STD
, &esid0
);
318 panic("Cannot set Aldebaran video i/o std!\n");
320 memset(&fmt
, 0, sizeof(fmt
));
321 fmt
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
322 fmt
.fmt
.pix
.width
= width
;
323 fmt
.fmt
.pix
.height
= height
;
324 fmt
.fmt
.pix
.pixelformat
= V4L2_PIX_FMT_YUYV
;
325 fmt
.fmt
.pix
.field
= V4L2_FIELD_INTERLACED
;
327 ret
= xioctl(fd
, VIDIOC_S_FMT
, &fmt
);
329 panic("Cannot set v4l format!\n");
331 set_v4l_ctl_or_die(fd
, V4L2_CID_AUTO_WHITE_BALANCE
, 0);
332 set_v4l_ctl_or_die(fd
, V4L2_CID_AUTOGAIN
, 0);
333 set_v4l_ctl_or_die(fd
, V4L2_CID_HUE_AUTO
, 0);
334 set_v4l_ctl_or_die(fd
, V4L2_CID_EXPOSURE_AUTO
, 0);
335 set_v4l_ctl_or_die(fd
, V4L2_CID_HFLIP
, 0);
336 set_v4l_ctl_or_die(fd
, V4L2_CID_VFLIP
, 0);
338 memset(&fps
, 0, sizeof(fps
));
339 fps
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
341 ret
= xioctl(fd
, VIDIOC_G_PARM
, &fps
);
343 panic("Cannot query fps param!\n");
345 fps
.parm
.capture
.timeperframe
.numerator
= 1;
346 fps
.parm
.capture
.timeperframe
.denominator
= 30;
348 ret
= xioctl(fd
, VIDIOC_S_PARM
, &fps
);
350 panic("Cannot set fps param!\n");
355 int cleanup_v4l_device(int fd
, unsigned int nbuffs
,
356 struct v4l_buff
*buffs
)
361 for (i
= 0; i
< nbuffs
; ++i
) {
362 ret
= munmap(buffs
[i
].start
, buffs
[i
].length
);
364 panic("Cannot munmap!\n");
371 void debug_v4l_struct_buffer(struct v4l2_buffer
*img
)
373 printf("index: %u\n", img
->index
);
374 printf("type: %u\n", img
->type
);
375 printf("bytes used: %u\n", img
->bytesused
);
376 printf("flags: %u (0x%x), mapped:%d, queued:%d, done:%d\n",
377 img
->flags
, img
->flags
,
378 (img
->flags
& V4L2_BUF_FLAG_MAPPED
),
379 (img
->flags
& V4L2_BUF_FLAG_QUEUED
),
380 (img
->flags
& V4L2_BUF_FLAG_DONE
));
381 printf("field: %u\n", img
->field
);
382 printf("sequence: %u\n", img
->sequence
);
383 printf("length: %u\n", img
->length
);
384 printf("input: %u\n", img
->input
);
385 printf("reserved: %u\n\n", img
->reserved
);