xref: /OK3568_Linux_fs/app/forlinx/flapp/src/plugins/imxx11/camera/camera.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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