1 #include "camera.h"
2 #include "ui_camera.h"
3 #include <unistd.h>
4 #include <assert.h>
5 #include <errno.h>
6 #include <sys/mman.h>
7 #include <sys/ioctl.h>
8 #include <sys/stat.h>
9 #include <linux/videodev2.h>
10 #include <QCloseEvent>
11 #include <QTimer>
12
13 static int fd = -1;
14 struct buffer
15 {
16 void * start;
17 size_t length;
18 };
19
20 struct buffer * buffers = NULL;
21 static unsigned int n_buffers = 0;
22 static unsigned int width = 800;
23 static unsigned int height = 480;
24 static char* deviceName = "/dev/video0";
25
26 char image_buf[1536000+54];
27
28 unsigned char bmp_h[] =
29 {
30 0x42,0x4d, //BM
31 0x42,0x70,0x17,0x00, // 1536000+66
32 0x00,0x00,0x00,0x00,
33 0x36,0x00,0x00,0x00, //bmp_data offset
34 0x28,0x00,0x00,0x00,
35 0x20,0x03,0x00,0x00, //width
36 0x20,0xfe,0xff,0xff, //hieght
37 0x01,0x00,
38 0x20,0x00, //32bit
39 0x00,0x00,0x00,0x00,
40 0x00,0x70,0x17,0x00, //bmp_data size
41 0x00,0x00,0x00,0x00,
42 0x00,0x00,0x00,0x00,
43 0x00,0x00,0x00,0x00,
44 0x00,0x00,0x00,0x00,
45 };
46
Camera(QWidget * parent)47 Camera::Camera(QWidget *parent) :
48 IWidget(parent),
49 ui(new Ui::Camera)
50 {
51 ui->setupUi(this);
52
53 timer = new QTimer;
54
55 this->imageWidget = new ImageWidget(this);
56 this->imageWidget->setBackgroundRole(QPalette::Dark);
57 this->imageWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
58 this->imageWidget->setObjectName(QString::fromUtf8("imageWidget"));
59 this->imageWidget->setGeometry(QRect(5, 50, 491, 371));
60 struct stat sta_buf;
61 if(::stat("/dev/video0",&sta_buf) < 0){
62 system("insmod /lib/modules/3.0.35-2666-gbdde708/kernel/drivers/media/video/mxc/capture/ipu_prp_enc.ko");
63 system("insmod /lib/modules/3.0.35-2666-gbdde708/kernel/drivers/media/video/mxc/capture/ipu_bg_overlay_sdc.ko");
64 system("insmod /lib/modules/3.0.35-2666-gbdde708/kernel/drivers/media/video/mxc/capture/ipu_fg_overlay_sdc.ko");
65 system("insmod /lib/modules/3.0.35-2666-gbdde708/kernel/drivers/media/video/mxc/capture/ipu_csi_enc.ko");
66 system("insmod /lib/modules/3.0.35-2666-gbdde708/kernel/drivers/media/video/mxc/capture/ipu_still.ko");
67 system("insmod /lib/modules/3.0.35-2666-gbdde708/kernel/drivers/media/video/mxc/capture/camera_sensor_clock.ko");
68 system("insmod /lib/modules/3.0.35-2666-gbdde708/kernel/drivers/media/video/mxc/capture/ov5640_camera.ko");
69 system("insmod /lib/modules/3.0.35-2666-gbdde708/kernel/drivers/media/video/mxc/capture/mxc_v4l2_capture.ko");
70 ::sleep(1);
71 }
72 connect(this->timer, SIGNAL(timeout()), this, SLOT(up_date()));
73
74 deviceOpen();
75 deviceInit();
76 captureStart();
77 }
78
~Camera()79 Camera::~Camera()
80 {
81 delete ui;
82 }
83
id()84 QString Camera::id()
85 {
86 return "camera";
87 }
88
closeEvent(QCloseEvent * event)89 void Camera::closeEvent(QCloseEvent *event)
90 {
91 deviceUninit();
92 event->accept(); //exit
93 }
94
deviceOpen(void)95 void deviceOpen(void)
96 {
97 fd = open(deviceName, O_RDWR | O_NONBLOCK, 0);
98
99 if (-1 == fd)
100 {
101 QMessageBox::about(NULL, "About", "camera open error");
102 exit(EXIT_FAILURE);
103 }
104 }
105
106
107 /* initialize device*/
108
deviceInit(void)109 void deviceInit(void)
110 {
111 struct v4l2_capability cap;
112 struct v4l2_cropcap cropcap;
113 struct v4l2_crop crop;
114 struct v4l2_format fmt;
115 unsigned int min;
116
117 if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap))
118 {
119 if (EINVAL == errno)
120 {
121 QMessageBox::about(NULL,"Information"," no V4L2 device");
122 exit(EXIT_FAILURE);
123 }
124 else
125 {
126 errno_exit("VIDIOC_QUERYCAP");
127 }
128 }
129
130 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
131 {
132 QMessageBox::about(NULL,"Information"," no video capture device");
133 exit(EXIT_FAILURE);
134 }
135
136 struct v4l2_input input;
137 input.index = 0;
138 if ( ioctl(fd, VIDIOC_ENUMINPUT, &input) != 0)
139 {
140 QMessageBox::about(NULL,"Information","set input error");
141 exit(0);
142 }
143
144 if ((ioctl(fd, VIDIOC_S_INPUT, &input)) < 0)
145 {
146 QMessageBox::about(NULL,"Information","set s_input error");
147 exit(0);
148 }
149
150 CLEAR(cropcap);
151
152 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
153
154
155 if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap))
156 {
157 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
158 crop.c.top = 0;
159 crop.c.left = 0;
160 crop.c.height = 720;
161 crop.c.width = 1280;
162
163 if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop))
164 {
165 switch (errno)
166 {
167 case EINVAL:
168 break;
169 default:
170 break;
171 }
172 }
173 }
174
175 CLEAR (fmt);
176
177 // v4l2_format
178 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
179 fmt.fmt.pix.width = width;
180 fmt.fmt.pix.height = height;
181 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR32;
182 //fmt.fmt.pix.field = V4L2_FIELD_ANY;
183
184 if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
185 errno_exit("VIDIOC_S_FMT");
186
187 /* Note VIDIOC_S_FMT may change width and height.*/
188 if (width != fmt.fmt.pix.width)
189 {
190 width = fmt.fmt.pix.width;
191 //fprintf(stderr,"Image width set to %i by device %s.\n",width,deviceName);
192 }
193 if (height != fmt.fmt.pix.height)
194 {
195 height = fmt.fmt.pix.height;
196 //fprintf(stderr,"Image height set to %i by device %s.\n",height,deviceName);
197 }
198
199 /*Buggy driver paranoia. */
200 min = fmt.fmt.pix.width * 2;
201 if (fmt.fmt.pix.bytesperline < min)
202 fmt.fmt.pix.bytesperline = min;
203
204 min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
205 if (fmt.fmt.pix.sizeimage < min)
206 fmt.fmt.pix.sizeimage = min;
207
208 mmapInit();
209 }
210
mmapInit(void)211 void mmapInit(void)
212 {
213 struct v4l2_requestbuffers req;
214 CLEAR (req);
215
216 req.count = 4;
217 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
218 req.memory= V4L2_MEMORY_MMAP;
219
220 if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req))
221 {
222 if (EINVAL == errno)
223 {
224 QMessageBox::about(NULL,"Information","does not support memory mapping");
225 exit(EXIT_FAILURE);
226 }
227 else
228 {
229 errno_exit("VIDIOC_REQBUFS");
230 }
231 }
232
233 if (req.count < 2)
234 {
235 QMessageBox::about(NULL,"Information","nsufficient buffer memory on device");
236 exit(EXIT_FAILURE);
237 }
238
239 buffers = (struct buffer*)calloc(req.count, sizeof(*buffers));
240
241 if (!buffers)
242 {
243 QMessageBox::about(NULL,"Information","Out of memory");
244 exit(EXIT_FAILURE);
245 }
246
247 for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
248 {
249 struct v4l2_buffer buf;
250
251 CLEAR (buf);
252
253 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
254 buf.memory = V4L2_MEMORY_MMAP;
255 buf.index = n_buffers;
256
257 if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
258 errno_exit("VIDIOC_QUERYBUF");
259
260 buffers[n_buffers].length = buf.length;
261
262 buffers[n_buffers].start =
263 mmap (NULL /* start anywhere */, buf.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, fd, buf.m.offset);
264
265 if (MAP_FAILED == buffers[n_buffers].start)
266 errno_exit("mmap");
267 }
268 }
269
captureStart(void)270 void captureStart(void)
271 {
272 unsigned int i;
273 enum v4l2_buf_type type;
274
275 for (i = 0; i < n_buffers; ++i)
276 {
277 struct v4l2_buffer buf;
278
279 CLEAR (buf);
280 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
281 buf.memory = V4L2_MEMORY_MMAP;
282 buf.index = i;
283
284 if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
285 errno_exit("VIDIOC_QBUF");
286 }
287
288 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
289
290 if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
291 errno_exit("VIDIOC_STREAMON");
292 }
293
mainLoop(unsigned char * src)294 void mainLoop(unsigned char* src)
295 {
296 unsigned int count;
297 count = 1;
298
299 while (count-- > 0)
300 {
301 for (;;)
302 {
303 fd_set fds;
304 struct timeval tv;
305 int r;
306
307 FD_ZERO(&fds);
308 FD_SET(fd, &fds);
309
310 /* Timeout. */
311 tv.tv_sec = 2;
312 tv.tv_usec = 0;
313
314 r = select(fd + 1, &fds, NULL, NULL, &tv);
315
316 if (-1 == r)
317 {
318 if (EINTR == errno)
319 continue;
320 errno_exit("select");
321 }
322
323 if (0 == r)
324 {
325 QMessageBox::about(NULL,"Information","select timeout");
326 exit(EXIT_FAILURE);
327 }
328 if (frameRead(src))
329 break;
330 }
331 }
332 }
333
frameRead(unsigned char * src)334 unsigned char* frameRead(unsigned char* src)
335 {
336 struct v4l2_buffer buf;
337
338 CLEAR (buf);
339
340 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
341 buf.memory = V4L2_MEMORY_MMAP;
342
343 if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf))
344 {
345 switch (errno)
346 {
347 case EAGAIN:
348 return 0;
349
350 case EIO:
351 default:
352 errno_exit("VIDIOC_DQBUF");
353 }
354 }
355 assert (buf.index < n_buffers);
356
357 imageProcess(buffers[buf.index].start,src);
358 // printf("frameR = %d\n",buffers[buf.index].start);
359
360 if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
361 errno_exit("VIDIOC_QBUF");
362
363 // return (unsigned char*)n;
364
365
366 }
367
imageProcess(const void * p,unsigned char * dst)368 unsigned char* imageProcess(const void* p,unsigned char* dst)
369 {
370 unsigned char* src = (unsigned char*)p;
371
372 memcpy(dst,bmp_h,54);
373 memcpy(dst+54,src,800*480*4);
374
375 return (unsigned char*)image_buf;
376
377 }
378
deviceUninit(void)379 void deviceUninit(void)
380 {
381 unsigned int i;
382
383 for (i = 0; i < n_buffers; ++i)
384 {
385 if (-1 == munmap (buffers[i].start, buffers[i].length))
386 errno_exit("munmap");
387 }
388
389 free(buffers);
390 close(fd);
391 }
392
errno_exit(const char * s)393 void errno_exit(const char* s)
394 {
395 Q_UNUSED(s)
396 //fprintf(stderr, "%s error %d, %s\n", s, errno, strerror (errno));
397 exit(EXIT_FAILURE);
398 }
399
400
xioctl(int fd,int request,void * argp)401 int xioctl(int fd, int request, void* argp)
402 {
403 int r;
404 do r = ioctl(fd, request, argp);
405 while (-1 == r && EINTR == errno);
406
407 return r;
408 }
409
changeEvent(QEvent * e)410 void Camera::changeEvent(QEvent *e)
411 {
412 QWidget::changeEvent(e);
413 switch (e->type())
414 {
415 case QEvent::LanguageChange:
416 ui->retranslateUi(this);
417 break;
418 default:
419 break;
420 }
421 }
422
up_date()423 void Camera::up_date()
424 {
425 unsigned char image_buf[1536000+54];
426 frameRead(image_buf);
427 this->imageWidget->setPixmap(image_buf);
428 }
429
430
on_pbt_start_clicked()431 void Camera::on_pbt_start_clicked()
432 {
433 timer->start(100);
434 }
435
on_pbt_stop_clicked()436 void Camera::on_pbt_stop_clicked()
437 {
438 timer->stop();
439 }
440