基于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环境下 编译即可运行。