视频监控系统

基于jz2440开发板的视屏监控系统lcd实时显示转载请注明出处https://www.cnblogs.com/xiao-yong/p/9596235.html

main函数:

  1 #include <stdio.h>
  2 
  3 #include <unistd.h>
  4 
  5 #include <stdlib.h>
  6 
  7 #include <string.h>
  8 
  9 #include <sys/ioctl.h>    
 10 
 11 #include <asm/types.h>          /* for videodev2.h */    
 12 
 13 #include <sys/time.h>   
 14 
 15 #include <sys/types.h>
 16 
 17 #include <sys/stat.h>
 18 
 19 #include <sys/mman.h>
 20 
 21 #include <fcntl.h>
 22 
 23 #include <error.h>    
 24 
 25 #include <errno.h>
 26 
 27 #include <malloc.h>   
 28 
 29 #include <linux/fb.h>
 30 
 31 #include <linux/videodev2.h>  
 32 
 33 #include <assert.h>
 34 
 35 #include "main.h"
 36 
 37 
 38 
 39 #define CLIP(color) (unsigned char)(((color)>0xFF)?0xff:(((color)<0)?0:(color)))
 40 
 41 
 42 
 43 
 44 
 45 static int *LutRv = NULL;
 46 
 47 static int *LutGu = NULL;
 48 
 49 static int *LutGv = NULL;
 50 
 51 static int *LutBu = NULL;
 52 
 53 
 54 
 55 
 56 
 57 struct buffer *buffers=NULL;
 58 
 59 
 60 
 61 
 62 
 63 void fb_init(Fb_dev *myfb)
 64 
 65 {
 66 
 67     struct fb_fix_screeninfo fb_fix;
 68 
 69     struct fb_var_screeninfo fb_var;
 70 
 71     
 72 
 73     //1、打开设备
 74 
 75     myfb->iFd = open(DEVICE_NAME, O_RDWR);
 76 
 77     //2、获取固定和可变参数
 78 
 79     ioctl(myfb->iFd, FBIOGET_FSCREENINFO, &fb_fix);
 80 
 81     ioctl(myfb->iFd, FBIOGET_VSCREENINFO, &fb_var);
 82 
 83     
 84 
 85     //3、打印屏幕参数
 86 
 87     printf("***********LCD-params****************
");
 88 
 89     printf("xres:%d, yres:%d
"
 90 
 91             "bits_per_pixel:%d
"
 92 
 93             "height:%d, %d
",
 94 
 95             fb_var.xres, fb_var.yres,
 96 
 97             fb_var.bits_per_pixel,
 98 
 99             fb_var.height, fb_var.width);
100 
101     printf("smem_start:%ld
"
102 
103             "smem_len:%d
"
104 
105             "line_length:%d
",
106 
107             fb_fix.smem_start,
108 
109             fb_fix.smem_len,
110 
111             fb_fix.line_length);
112 
113     printf("**************end********************
");  
114 
115     
116 
117     myfb->iWidth      = fb_var.xres;/* 宽度: 一行有多少个象素 */
118 
119     myfb->iHeight     = fb_var.yres;/* 高度: 一列有多少个象素 */
120 
121     myfb->iBpp           = fb_var.bits_per_pixel;/* 一个象素用多少位来表示 */
122 
123     myfb->iLineBytes     = fb_var.xres*fb_var.bits_per_pixel/8;/* 一行数据有多少字节 */
124 
125     myfb->iTotalBytes     = fb_var.yres*myfb->iLineBytes;/* 所有字节数 */
126 
127     
128 
129     //5、进行映射
130 
131     myfb->fb_addr = (char *)mmap(0,myfb->iTotalBytes,PROT_READ|PROT_WRITE, MAP_SHARED, myfb->iFd, 0);
132 
133      
134 
135 }
136 
137 
138 
139 
140 
141 
142 
143 
144 
145 
146 
147 void initLut(void)
148 
149 {
150 
151     int i;
152 
153     #define CoefRv 1402
154 
155     #define CoefGu 714 // 344
156 
157     #define CoefGv 344 // 714
158 
159     #define CoefBu 1772
160 
161     
162 
163     LutRv = malloc(256*sizeof(int));
164 
165     LutGu = malloc(256*sizeof(int));
166 
167     LutGv = malloc(256*sizeof(int));
168 
169     LutBu = malloc(256*sizeof(int));
170 
171     
172 
173     for (i= 0;i < 256;i++){
174 
175         LutRv[i] = (i-128)*CoefRv/1000;
176 
177         LutBu[i] = (i-128)*CoefBu/1000;
178 
179         LutGu[i] = (128-i)*CoefGu/1000;
180 
181         LutGv[i] = (128-i)*CoefGv/1000;
182 
183     }    
184 
185 }
186 
187 
188 
189 void freeLut(void){
190 
191     free(LutRv);
192 
193     free(LutGu);
194 
195     free(LutGv);
196 
197     free(LutBu);
198 
199 }
200 
201 
202 
203 
204 
205 
206 
207 
208 
209 unsigned char R_FROMYV(unsigned char y, unsigned char v)
210 
211 {
212 
213     return CLIP((y) + LutRv[(v)]);
214 
215 }
216 
217 unsigned char G_FROMYUV(unsigned char y, unsigned char u, unsigned char v)
218 
219 {
220 
221     return CLIP((y) + LutGu[(u)] + LutGv[(v)]);
222 
223 }
224 
225 unsigned char B_FROMYU(unsigned char y, unsigned char u)
226 
227 {
228 
229     return CLIP((y) + LutBu[(u)]);
230 
231 }
232 
233 
234 
235 
236 
237 unsigned int Pyuv422torgb565(unsigned char * input_ptr, unsigned char * output_ptr, unsigned int image_width, unsigned int image_height)
238 
239 {
240 
241     unsigned int i, size;
242 
243     unsigned char Y, Y1, U, V;
244 
245     unsigned char *buff = input_ptr;
246 
247     unsigned char *output_pt = output_ptr;
248 
249 
250 
251     unsigned int r, g, b;
252 
253     unsigned int color;
254 
255     
256 
257     size = image_width * image_height /2;
258 
259     for (i = size; i > 0; i--) {
260 
261         /* bgr instead rgb ?? */
262 
263         Y = buff[0] ;
264 
265         U = buff[1] ;
266 
267         Y1 = buff[2];
268 
269         V = buff[3];
270 
271         buff += 4;
272 
273         r = R_FROMYV(Y,V);
274 
275         g = G_FROMYUV(Y,U,V); //b
276 
277         b = B_FROMYU(Y,U); //v
278 
279 
280 
281         /* 把r,g,b三色构造为rgb565的16位值 */
282 
283         r = r >> 3;
284 
285         g = g >> 2;
286 
287         b = b >> 3;
288 
289         color = (r << 11) | (g << 5) | b;
290 
291         *output_pt++ = color & 0xff;
292 
293         *output_pt++ = (color >> 8) & 0xff;
294 
295             
296 
297         r = R_FROMYV(Y1,V);
298 
299         g = G_FROMYUV(Y1,U,V); //b
300 
301         b = B_FROMYU(Y1,U); //v
302 
303         
304 
305         /* 把r,g,b三色构造为rgb565的16位值 */
306 
307         r = r >> 3;
308 
309         g = g >> 2;
310 
311         b = b >> 3;
312 
313         color = (r << 11) | (g << 5) | b;
314 
315         *output_pt++ = color & 0xff;
316 
317         *output_pt++ = (color >> 8) & 0xff;
318 
319     }
320 
321     
322 
323     return 0;
324 
325 } 
326 
327 
328 
329 
330 
331 
332 
333 /********************************
334 
335 *函数功能:初始化摄像头+显示摄像头信息
336 
337 *********************************/
338 
339 void init_device(Cam_dev *camdev,Fb_dev *myfb)
340 
341 {
342 
343     unsigned int n_buffers;
344 
345     struct v4l2_requestbuffers req;
346 
347     struct v4l2_capability cap;
348 
349     struct v4l2_fmtdesc fmtdesc;
350 
351     struct v4l2_format fmt;
352 
353     
354 
355     //0、打开摄像头
356 
357     if((camdev->cfd=open(dev_name,O_RDWR|O_NONBLOCK,0))<0)
358 
359     {
360 
361     printf("device:%s open failed!!
",dev_name);    
362 
363     exit(-1);
364 
365     }
366 
367     
368 
369     //1、查询摄像头信息并打印
370 
371     if (ioctl(camdev->cfd, VIDIOC_QUERYCAP, &cap) == -1) 
372 
373     {
374 
375         printf("Error opening device %s: unable to query device.
",dev_name);
376 
377         exit(-1);
378 
379     }
380 
381     else
382 
383     {
384 
385         /*打印信息*/
386 
387         printf("*************Camera-params***************
");
388 
389         printf("driver:		%s
",    cap.driver);
390 
391         printf("card:		%s
",        cap.card);
392 
393         printf("bus_info:	%s
",    cap.bus_info);
394 
395         printf("version:	%d
",    cap.version);
396 
397         printf("capabilities:	%x
",    cap.capabilities);
398 
399         printf("*****************end*********************
");
400 
401          
402 
403         /*检测摄像头是否支持图像抓取功能*/
404 
405         if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE) 
406 
407         {
408 
409             printf("Device %s: supports capture.
",dev_name);
410 
411         }
412 
413     /*检测摄像头是否支持视频流*/
414 
415         if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING) 
416 
417         {
418 
419             printf("Device %s: supports streaming.
",dev_name);
420 
421         }
422 
423     }
424 
425 
426 
427     //2、打印所有支持格式
428 
429     ///////////////////////////////////////////////////////////////
430 
431     printf("Support format:
");
432 
433     fmtdesc.index    = 0;
434 
435     fmtdesc.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
436 
437     while(ioctl(camdev->cfd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)
438 
439     {
440 
441         printf("	%d.%s
",fmtdesc.index+1,fmtdesc.description);
442 
443         fmtdesc.index++;
444 
445     }
446 
447     /////////////////////////////////////////////////////////////////
448 
449     
450 
451     //3、设置摄像头格式
452 
453     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
454 
455     fmt.fmt.pix.height         = myfb->iHeight;
456 
457     fmt.fmt.pix.width         = myfb->iWidth;
458 
459     fmt.fmt.pix.field         = V4L2_FIELD_ANY;//V4L2_FIELD_INTERLACED;
460 
461     fmt.fmt.pix.pixelformat     = V4L2_PIX_FMT_YUYV;
462 
463     
464 
465     if (-1 == ioctl(camdev->cfd, VIDIOC_S_FMT, &fmt))  
466 
467     { 
468 
469         printf("VIDIOC_S_FMT error!
");
470 
471     exit(-1);   
472 
473     }
474 
475         
476 
477     if(ioctl(camdev->cfd, VIDIOC_G_FMT, &fmt) == -1)
478 
479     {
480 
481         printf("Unable to get format
");
482 
483         exit(-1); 
484 
485     } 
486 
487 
488 
489     printf("fmt.type:		%d
",fmt.type);
490 
491     printf("pix.pixelformat:	%c%c%c%c
",fmt.fmt.pix.pixelformat & 0xFF, (fmt.fmt.pix.pixelformat >> 8) & 0xFF,(fmt.fmt.pix.pixelformat >> 16) & 0xFF, (fmt.fmt.pix.pixelformat >> 24) & 0xFF);
492 
493     printf("pix.height:		%d
",fmt.fmt.pix.height);
494 
495     printf("pix.		%d
",fmt.fmt.pix.width);
496 
497     printf("pix.field:		%d
",fmt.fmt.pix.field);
498 
499     //保存摄像头图像像素信息
500 
501     camdev->cWidth      = fmt.fmt.pix.width;
502 
503     camdev->cHeight     = fmt.fmt.pix.height;
504 
505     camdev->cLineBytes    = fmt.fmt.pix. bytesperline;
506 
507     camdev->cTotalBytes = fmt.fmt.pix. sizeimage;
508 
509  
510 
511     //4、请求四个缓冲帧
512 
513     req.count    = REBUF_CNT;
514 
515     req.memory    = V4L2_MEMORY_MMAP;
516 
517     req.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;
518 
519     
520 
521     if(ioctl(camdev->cfd,VIDIOC_REQBUFS,&req)==-1)
522 
523     {
524 
525         printf("request for buffers error!
");
526 
527     }
528 
529     if (req.count < 2)
530 
531     {
532 
533         printf("Insufficient buffer memory on %s
",dev_name); 
534 
535            exit(-1);
536 
537     }
538 
539     
540 
541     //2、分配图像缓冲结构 (mmap for buffers) 
542 
543     buffers = calloc(req.count, sizeof (struct buffer));  
544 
545     if (!buffers) 
546 
547     {
548 
549         printf ("Out of memory: error!
");
550 
551         exit(-1);
552 
553     }
554 
555     
556 
557     //3、把内核空间中的图像缓冲区映射到用户空间 
558 
559     for (n_buffers = 0; n_buffers < req.count; ++n_buffers) 
560 
561     {   
562 
563     struct v4l2_buffer buf;   
564 
565         
566 
567     CLEAR(buf);   
568 
569     buf.index       = n_buffers;
570 
571     buf.memory      = V4L2_MEMORY_MMAP;          
572 
573     buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;   
574 
575     
576 
577     /*获取要映射屏幕大小*/
578 
579     if (-1 == ioctl(camdev->cfd, VIDIOC_QUERYBUF, &buf))   
580 
581     {
582 
583          printf ("VIDIOC_QUERYBUF error!
");
584 
585         exit(-1);   
586 
587     }    
588 
589     
590 
591     /*这里的输出是为了检查有关参数的大小*/
592 
593     camdev->cTotalBytes       = buf.length;   
594 
595     
596 
597     buffers[n_buffers].length = buf.length;   
598 
599     
600 
601     
602 
603     buffers[n_buffers].start =   
604 
605         mmap(NULL /* start anywhere */,   
606 
607         buf.length,   
608 
609         PROT_READ | PROT_WRITE /* required */,   
610 
611         MAP_SHARED /* recommended */,   
612 
613         camdev->cfd, buf.m.offset);   
614 
615     /*不成功则退出*/
616 
617     if (MAP_FAILED == buffers[n_buffers].start)   
618 
619     {
620 
621          printf ("mmap error!
");
622 
623         exit(-1);   
624 
625     }  
626 
627     } 
628 
629     
630 
631     /*将缓冲帧放入队列*/
632 
633     for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
634 
635     {   
636 
637     struct v4l2_buffer buf;   
638 
639     CLEAR(buf);   
640 
641     
642 
643     buf.index       = n_buffers;   
644 
645     buf.memory      = V4L2_MEMORY_MMAP;   
646 
647     buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
648 
649         
650 
651     if (-1 == ioctl(camdev->cfd, VIDIOC_QBUF, &buf))   
652 
653     {
654 
655          printf ("VIDIOC_QBUF error!
");
656 
657         exit(-1);   
658 
659     }  
660 
661     }   
662 
663     
664 
665     camdev->displaybuf =(char*)malloc(camdev->cTotalBytes);
666 
667     
668 
669 }
670 
671 
672 
673 
674 
675 /********************************
676 
677 *函数功能:启动捕获图像
678 
679 *********************************/
680 
681 void start_capture(int cfd)
682 
683 {
684 
685     /*帧类型,应用程序设置  */
686 
687     enum v4l2_buf_type type;
688 
689  
690 
691     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;   
692 
693     /*启动数据流*/
694 
695     if (-1 == ioctl(cfd, VIDIOC_STREAMON, &type))  
696 
697     {
698 
699          printf ("VIDIOC_STREAMON error!
");
700 
701         exit(-1);   
702 
703     }    
704 
705     printf ("Start Video Capturing!
");
706 
707 }
708 
709 
710 
711 
712 
713 void display_pic(Cam_dev *camdev,Fb_dev *myfb)
714 
715 {
716 
717     struct v4l2_buffer buf;   
718 
719     unsigned char* ptmp;
720 
721     unsigned long i,j;
722 
723     
724 
725     CLEAR (buf);   
726 
727     buf.memory     = V4L2_MEMORY_MMAP;   
728 
729     buf.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;   
730 
731     
732 
733     /*取出一缓冲帧*/
734 
735     if (-1 == ioctl(camdev->cfd, VIDIOC_DQBUF, &buf)) 
736 
737     {   
738 
739     printf(" VIDIOC_DQBUF error!
");
740 
741     exit(-1);
742 
743     }   
744 
745     /*检查缓冲帧是否有效*/
746 
747     assert(buf.index < 4);  
748 
749      
750 
751     /*图片格式转换:YUV422->RGB565*/
752 
753     ptmp = (unsigned char*)buffers[buf.index].start;
754 
755     
756 
757     Pyuv422torgb565(ptmp,camdev->displaybuf,camdev->cHeight,camdev->cWidth);
758 
759     
760 
761     PicMerge(camdev,myfb);
762 
763     
764 
765     if (-1 == ioctl(camdev->cfd, VIDIOC_QBUF, &buf))   
766 
767     {
768 
769         printf("VIDIOC_QBUF error!
");
770 
771     exit(-1);    
772 
773     }
774 
775 }
776 
777 
778 
779 
780 
781 int PicMerge(Cam_dev *camdev,Fb_dev *myfb)
782 
783 {
784 
785     int i;
786 
787     int iX,iY;
788 
789     unsigned char *pucSrc;
790 
791     unsigned char *pucDst;
792 
793     
794 
795     iX = (myfb->iWidth -camdev->cWidth )/2;
796 
797     iY = (myfb->iHeight -camdev->cHeight )/2;
798 
799     
800 
801        //指向放缩后的图像
802 
803     pucSrc = camdev->displaybuf;
804 
805     //计算空出来的起始的空格
806 
807     pucDst = myfb->fb_addr + iY * myfb->iLineBytes + iX *myfb->iBpp/8;
808 
809     
810 
811     for (i = 0; i <camdev->cHeight; i++)
812 
813     {
814 
815         memcpy(pucDst, pucSrc, camdev->cLineBytes);
816 
817         pucSrc += camdev->cLineBytes;
818 
819         pucDst += myfb->iLineBytes;
820 
821     }
822 
823     return 0;
824 
825 }
826 
827 
828 
829 
830 
831 
832 
833 
834 
835 
836 
837 
838 void uninit_device(Cam_dev *camdev,Fb_dev *myfb)
839 
840 {
841 
842     unsigned int i;
843 
844     for (i = 0; i < REBUF_CNT; ++i)
845 
846       munmap (buffers[i].start, buffers[i].length);   
847 
848     free(buffers);  
849 
850     free(camdev->displaybuf);
851 
852     close(camdev->cfd);
853 
854     close(myfb->iFd);
855 
856     printf("quit!!
");
857 
858 }
859 
860 
861 
862 
863 
864 
865 
866 
867 
868 
869 
870 int main(void)
871 
872 {
873 
874     int ret;
875 
876     fd_set fds;
877 
878     struct timeval tv; 
879 
880         
881 
882            Fb_dev  myfb;   //显示设备
883 
884            Cam_dev camdev; //图像采集设备
885 
886            
887 
888     //1、初始化显示设备
889 
890     fb_init(&myfb);
891 
892     init_device(&camdev,&myfb);
893 
894     initLut();//初始化颜色转换
895 
896     //4、开启捕捉视频
897 
898     start_capture(camdev.cfd);
899 
900     
901 
902     while(1)
903 
904     {
905 
906             /*每次循环都要清空*/
907 
908         FD_ZERO(&fds);   
909 
910         /*添加描述符*/
911 
912         FD_SET(camdev.cfd, &fds);   
913 
914         
915 
916         /* Timeout. */   
917 
918         tv.tv_sec  = 20;   
919 
920         tv.tv_usec = 0;   
921 
922         ret = select (camdev.cfd + 1, &fds, NULL, NULL, NULL);   
923 
924           
925 
926         /*select错误,退出*/
927 
928         if (-1 == ret) 
929 
930         {   
931 
932             printf("Select() error!
");
933 
934             //exit(-1);   
935 
936             break;
937 
938         }   
939 
940         if (0 == ret) {   
941 
942             printf("select timeout
");   
943 
944             continue;   
945 
946         }   
947 
948         if(FD_ISSET(camdev.cfd, &fds))
949 
950         {
951 
952             display_pic(&camdev,&myfb);
953 
954         }
955 
956     
957 
958             
959 
960     }
961 
962         
963 
964     freeLut();//释放颜色转换空间
965 
966     uninit_device(&camdev,&myfb);
967 
968     return 0;    
969 
970 }

.h文件

  1 #ifndef _V4L2_INIT
  2 
  3 #define _V4L2_INIT
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 #define dev_name "/dev/video0"
 12 
 13 #define REBUF_CNT  4
 14 
 15 #define CLEAR(x) memset(&(x), 0, sizeof (x))  
 16 
 17 
 18 
 19 
 20 
 21 typedef struct fbdev
 22 
 23 {
 24 
 25     int iFd;      /*lcd文件描述符*/
 26 
 27     int iWidth;   /* 宽度: 一行有多少个象素 */
 28 
 29     int iHeight;  /* 高度: 一列有多少个象素 */
 30 
 31     int iBpp;     /* 一个象素用多少位来表示 */
 32 
 33     int iLineBytes;  /* 一行数据有多少字节 */
 34 
 35     int iTotalBytes; /* 所有字节数 */ 
 36 
 37     char *fb_addr;//用户层映射后的地址
 38 
 39 }Fb_dev;
 40 
 41 
 42 
 43 #define DEVICE_NAME "/dev/fb0"
 44 
 45 
 46 
 47 void fb_init(Fb_dev *myfb);
 48 
 49 
 50 
 51 unsigned int 
 52 
 53 Pyuv422torgb565(unsigned char * input_ptr, unsigned char * output_ptr, 
 54 
 55         unsigned int image_width, unsigned int image_height);
 56 
 57         
 58 
 59 void initLut(void);
 60 
 61 void freeLut(void);
 62 
 63 /*******************************
 64 
 65 *用来存放帧缓冲地址和长度
 66 
 67 *******************************/
 68 
 69 struct buffer
 70 
 71 {
 72 
 73     void * start;
 74 
 75     unsigned int length;
 76 
 77 };
 78 
 79 
 80 
 81 
 82 
 83 typedef struct camdev
 84 
 85 {
 86 
 87     int cfd;      /*lcd文件描述符*/
 88 
 89     int cWidth;   /* 宽度: 一行有多少个象素 */
 90 
 91     int cHeight;  /* 高度: 一列有多少个象素 */
 92 
 93     int cLineBytes;  /* 一行数据有多少字节 */
 94 
 95     int cTotalBytes; /* 所有字节数 */ 
 96 
 97     char *displaybuf;
 98 
 99 }Cam_dev;
100 
101 
102 
103 void init_device(Cam_dev *camdev,Fb_dev *myfb);
104 
105 void start_capture(int cfd);
106 
107 void yuv422_2_rgb(unsigned char* ptr);
108 
109 void display_pic(Cam_dev *camdev,Fb_dev *myfb);
110 
111 int PicMerge(Cam_dev *camdev,Fb_dev *myfb);
112 
113 
114 
115 void uninit_device(Cam_dev *camdev,Fb_dev *myfb);
116 
117 
118 
119 
120 
121 #endif

直接拷贝到linux环境下 编译即可运行。

原文地址:https://www.cnblogs.com/xiao-yong/p/9596235.html