41
41
#include <v4l2_layer.h>
43
#define ARRAY_RESOLUTION_SIZE 30
43
45
FACTORY_REGISTER_INSTANTIATOR(Layer, V4L2CamLayer, CamLayer, v4l2);
49
m_sizes = (int(*)[2]) malloc(sz * sizeof(*m_sizes));
55
if(m_sizes) free(m_sizes);
58
bool Res::addRes(int x, int y, int type) {
59
if (type == V4L2_FRMSIZE_TYPE_DISCRETE) {
60
if (m_idx < (m_size -1)) {
61
m_sizes[m_idx][0] = x;
62
m_sizes[m_idx][1] = y;
63
std::cerr << "--" << m_sizes[m_idx][0] << "x" << y << std::endl;
72
m_sizes[m_idx][0] = x;
73
m_sizes[m_idx][1] = y;
86
int Res::getX(int val) {
87
if ((val < m_idx) && (val >= 0))
88
return (m_sizes[val][0]);
94
int Res::getY(int val) {
95
if ((val < m_idx) && (val >= 0))
96
return (m_sizes[val][1]);
102
void Res::setsX(int x) {
103
for (int i; i < m_idx; i++) {
104
if (x == m_sizes[i][0]) {
111
int Res::getCurIdx() {
115
void Res::chgRes(int line) {
117
// first, turn off streaming
118
/* if(-1 == ioctl(m_fd, VIDIOC_STREAMOFF, &buftype)) {
119
error("VIDIOC_STREAMOFF: %s", errno);
124
/* for (unsigned int i = 0; i < reqbuf.count; i++)
125
munmap (buffers[i].start, buffers[i].length);
126
memset (&m_format, 0, sizeof (m_format));
127
m_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
129
if (-1 == ioctl (m_fd, VIDIOC_G_FMT, &m_format)) {
130
perror ("VIDIOC_G_FMT");
133
// memset (&m_format, 0, sizeof (m_format));
134
// m_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
135
/* m_format.fmt.pix.width = m_sizes[line][0];
136
m_format.fmt.pix.height = m_sizes[line][1];
137
m_format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
138
m_format.fmt.pix.field = V4L2_FIELD_ANY;
139
if(0 == ioctl(m_fd, VIDIOC_TRY_FMT, &m_format)) {
140
std::cerr << "--- we should be able to setup the resolution :)" << std::endl;
141
if(-1 == ioctl(m_fd, VIDIOC_S_FMT, &m_format)) {
142
error("VIDIOC_G_FMT: %s", strerror(errno));
45
149
V4L2CamLayer::V4L2CamLayer()
112
219
standard.index++;
115
//displays the format description
222
//fills the frame size the format description
116
223
memset (&fmtdesc, 0, sizeof (fmtdesc));
117
224
fmtdesc.index = 0;
118
225
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
119
226
while (0 == ioctl (fd, VIDIOC_ENUM_FMT, &fmtdesc)) {
120
227
std::cerr << "----- format description :" << fmtdesc.description << std::endl;
229
m_res = new Res (ARRAY_RESOLUTION_SIZE);
231
memset(&framesize, 0, sizeof framesize);
232
framesize.pixel_format = fmtdesc.pixelformat;
234
int ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &framesize);
237
if (i != framesize.index)
238
error ("Warning: driver returned wrong frame index "
239
"%u.\n", framesize.index);
240
if (fmtdesc.pixelformat != framesize.pixel_format)
241
error("Warning: driver returned wrong frame pixel "
242
"format %08x.\n", framesize.pixel_format);
244
switch (framesize.type) {
245
case V4L2_FRMSIZE_TYPE_DISCRETE:
246
m_res->addRes (framesize.discrete.width, framesize.discrete.height, V4L2_FRMSIZE_TYPE_DISCRETE);
249
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
250
m_res->addRes (framesize.stepwise.max_width, framesize.stepwise.max_height, V4L2_FRMSIZE_TYPE_CONTINUOUS);
251
m_res->addRes (framesize.stepwise.min_width, framesize.stepwise.min_height, V4L2_FRMSIZE_TYPE_CONTINUOUS);
254
case V4L2_FRMSIZE_TYPE_STEPWISE:
255
m_res->addRes (framesize.stepwise.max_width, framesize.stepwise.max_height, V4L2_FRMSIZE_TYPE_STEPWISE);
256
m_res->addRes (framesize.stepwise.min_width, framesize.stepwise.min_height, V4L2_FRMSIZE_TYPE_STEPWISE);
257
m_res->addRes (framesize.stepwise.step_width, framesize.stepwise.step_height, V4L2_FRMSIZE_TYPE_STEPWISE);
267
//gets the current resolution
124
268
memset (&format, 0, sizeof (format));
125
269
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
277
m_res->setsX(format.fmt.pix.width);
132
279
///////////// does not work with my ricoh and the uvcvideo module .... just comment out if needed
133
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
134
format.fmt.pix.width = 352;
135
format.fmt.pix.height = 288;
136
format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
137
format.fmt.pix.field = V4L2_FIELD_ANY;
138
if(0 == ioctl(fd, VIDIOC_TRY_FMT, &format)) {
139
std::cerr << "--- we should be able to setup the resolution :)" << std::endl;
140
if(-1 == ioctl(fd, VIDIOC_S_FMT, &format)) {
141
error("VIDIOC_G_FMT: %s", strerror(errno));
280
// format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
281
// format.fmt.pix.width = 352;
282
// format.fmt.pix.height = 288;
283
// format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
284
// format.fmt.pix.field = V4L2_FIELD_ANY;
285
// if(0 == ioctl(fd, VIDIOC_TRY_FMT, &format)) {
286
// std::cerr << "--- we should be able to setup the resolution :)" << std::endl;
287
// if(-1 == ioctl(fd, VIDIOC_S_FMT, &format)) {
288
// error("VIDIOC_S_FMT: %s", strerror(errno));
146
293
// Need to find out (request?) specific data format (sec 1.10.1)
147
294
memset(&format, 0, sizeof(format));
434
void V4L2CamLayer::chgRes(int idx, Res *res) {
437
// first, turn off streaming
438
if(-1 == ioctl(fd, VIDIOC_STREAMOFF, &buftype)) {
439
error("VIDIOC_STREAMOFF: %s", errno);
442
for (unsigned int i = 0; i < reqbuf.count; i++)
443
munmap (buffers[i].start, buffers[i].length);
445
if (-1 == ::close (fd)) {
446
error ("can't close the v4l2 opened device : %s", strerror (errno));
450
if (-1 == (fd = ::open(m_devfile,O_RDWR|O_NONBLOCK))) {
451
error("error in opening video capture device: %s", m_devfile);
456
fd = ::open(m_devfile,O_RDWR);
460
// Switch to the first video input (example 1-2)
462
if(-1 == ioctl(fd, VIDIOC_G_INPUT, &index)) { //gets the current video input
463
error("VIDIOC_G_INPUT: %s", strerror(errno));
467
// change the resolution
468
memset (&format, 0, sizeof (format));
469
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
471
if (-1 == ioctl (fd, VIDIOC_G_FMT, &format)) {
472
perror ("VIDIOC_G_FMT");
476
// memset (&format, 0, sizeof (format));
477
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
478
format.fmt.pix.width = res->getX(idx);
479
format.fmt.pix.height = res->getY(idx);
480
format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
481
format.fmt.pix.field = V4L2_FIELD_ANY;
482
if(0 == ioctl(fd, VIDIOC_TRY_FMT, &format)) {
483
if(-1 == ioctl(fd, VIDIOC_S_FMT, &format)) {
484
error("VIDIOC_S_FMT: %s", strerror(errno));
489
memset (&format, 0, sizeof (format));
490
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
492
if (-1 == ioctl (fd, VIDIOC_G_FMT, &format)) {
493
perror ("VIDIOC_G_FMT");
497
if ((format.fmt.pix.width != res->getX(idx)) || (format.fmt.pix.height != res->getY(idx))) {
498
error ("couldn't change the resolution, still : %dx%d", format.fmt.pix.width, format.fmt.pix.height);
502
geo.init(format.fmt.pix.width, format.fmt.pix.height, 32);
504
frame = malloc(geo.bytesize);
506
//////// init buffers
507
memset (&reqbuf, 0, sizeof (reqbuf));
508
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
509
reqbuf.memory = V4L2_MEMORY_MMAP;
510
reqbuf.count = 4; //reduced to reduce the display delay (thanks snawrocki)
511
if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
513
error("video capturing by mmap-streaming is not supported");
515
error ("VIDIOC_REQBUFS: %s", strerror(errno));
519
act("this cam supports %i buffers", reqbuf.count);
521
buffers = (bufs*)calloc (reqbuf.count, sizeof (*buffers));
523
if(format.fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV) { // YUYV
524
warning("pixel format not recognized, trying anyway as YUYV");
525
warning("the system might become instable...");
528
for (unsigned int i = 0; i < reqbuf.count; i++) {
530
memset (&buffer, 0, sizeof (buffer));
531
buffer.type = reqbuf.type;
532
buffer.memory = V4L2_MEMORY_MMAP;
535
if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
536
error ("VIDIOC_QUERYBUF: %s", strerror(errno));
540
buffers[i].length = buffer.length; /* remember for munmap() */
542
buffers[i].start = mmap (NULL, buffer.length,
543
PROT_READ | PROT_WRITE, /* recommended */
544
MAP_SHARED, /* recommended */
545
fd, buffer.m.offset);
547
if (MAP_FAILED == buffers[i].start) {
548
/* If you do not exit here you should unmap() and free()
549
* the buffers mapped so far. */
550
error ("mmap: %s", strerror(errno));
556
// OK, the memory is mapped, so let's queue up the buffers, turn on
557
// streaming, and do the business
559
// queue up all the buffers for the first time
560
for (unsigned int i = 0; i < reqbuf.count; i++) {
562
memset (&buffer, 0, sizeof (buffer));
563
buffer.type = reqbuf.type;
564
buffer.memory = V4L2_MEMORY_MMAP;
566
buffer.length = buffers[i].length;
568
if (-1 == ioctl (fd, VIDIOC_QBUF, &buffer)) {
569
error ("first VIDIOC_QBUF: %s", strerror(errno));
576
if(-1 == ioctl(fd, VIDIOC_STREAMON, &buftype)) {
577
error("VIDIOC_STREAMON: %s", strerror(errno));
282
585
void V4L2CamLayer::close() {
283
586
if(!opened) return;
284
587
// If we've finished, turn off streaming