We all know, want to drive Linux under the camera, actually very simple, follow the V4L2 manual step by step to write, soon can be written out, but before writing we should pay attention to change some configuration of the system, so that the system support framebuffer, under the dev fb0 such nodes, So that we can operate the camera camera on the Linux system, framebuffer in the previous post has been said, here is no longer mentioned.
There is a need to know about framebuffer. Please click: http://baike.baidu.com/view/3351639.htm
Most importantly, we need to change a script in/dev/grub.conf, let's see How to change:
# grub.conf generated by anaconda## Note so you don't have to rerun grub after making changes to this file# notice:
you has a/boot partition. This means that# all kernel and initrd paths is relative to/boot/, eg.# root (hd0,0) # Kernel/vmlinuz-versio n ro root=/dev/sdb2# initrd/initrd-[generic-]version.img#boot=/dev/sdbdefault=0timeout=5splashimage= (hd0,0)/ Grub/splash.xpm.gzhiddenmenutitle CentOS (2.6.32-431.el6.i686) root (hd0,0) kernel/vmlinuz-2.6.32-431.el6.i686 ro root=uuid=2bc12537-d6c1-4e67-b4e5-e9c466205554 nomodeset rd_no_luks keyboardtype=pc KEYTABLE=us Rd_NO_MD Crashkernel=auto LANG=ZH_CN. UTF-8 RD_NO_LVM rd_no_dm rhgb quiet vga=0x318initrd/initramfs-2.6.32-431.el6.i686.img
Usually, for framebuffer to take effect, add a sentence of vga=??? (Here are the parameters), a brief introduction:
I write vga=0x318 is set to 1024X768X24BPP mode by default. There are, of course, other patterns: for example, to configure according to your own system.
| Color |
640x400 |
640x480 |
800x600 |
1024x768 |
1280x1024 |
1600x1200 |
| 4bits |
? |
? |
0x302 |
? |
? |
? |
| 8bits |
0x300 |
0x301 |
0x303 |
0x305 |
0x307 |
0x31c |
| 15bits |
? |
0x310 |
0x313 |
0x316 |
0x319 |
0x31d |
| 16bits |
? |
0x311 |
0x314 |
0x317 |
0x31a |
0x31e |
| 24bits |
? |
0x312 |
0x315 |
0x318 |
0x31b |
0x31f |
| 32bits |
? |
? |
? |
? |
? |
? |
After the configuration is complete, let's take a look at the main features of V4L2. V4L2 makes the program capable of discovering equipment and operating equipment. It mainly uses a series of callback functions to implement these functions. Like setting the camera frequency, frame rate, video compression format and image parameters and so on. Of course, it can also be used for other multimedia development, such as audio. However, this framework can only run on Linux operating systems.V4L2 is a programming framework for UVC free-drive USB devices, mainly used for capturing USB camera, etc., the programming mode is as follows:
Collection mode when the video device is turned on, you can set properties for the video device, such as cropping, zooming, and so on. This step is optional. In Linux programming, the IOCTL function is generally used to manage the I/O channel of a device:
extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;__FD: The ID of the device, such as the camerafd;__ returned after opening the video channel with the Open function Request: A specific command marker. In V4L2 development, the following command flags are typically used: Vidioc_reqbufs: Allocating memory Vidioc_querybuf: Converting the data cache allocated in Vidioc_reqbufs to physical addresses VIDIOC_ Querycap: Query-driven vidioc_enum_fmt: Get current driver-supported video formats VIDIOC_S_FMT: Set the current drive's frequency capture format vidioc_g_fmt: Read the current drive's frequency capture format Vidioc_try_ FMT: Verifying the display format of the current drive Vidioc_cropcap: query-driven trimming capability Vidioc_s_crop: Sets the border of the video signal Vidioc_g_crop: reads the border of the video signal VIDIOC_ QBUF: Put the data back into the cache queue Vidioc_dqbuf: Read the data out of the cache Vidioc_streamon: Start video display function Vidioc_streamoff: End video Display function vidioc_ QUERYSTD: Check the standards supported by the current video device, such as PAL or NTSC. Some of these IO calls are required, and some are optional.
V4L2 Operation flow: Click this URL, said very detailed, here not much to say. Http://baike.baidu.com/view/5494174.htmNext we take a look at the actual combat section, the following is my own programming interface, can achieve video capture:1, project.c
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include "j-yuv.h" #include "CameralOpt.h" # Include "FrameBufferOpt.h" #define WIDTH 640#define HIGHT 480int Main (void) {char yuyv[width*hight* 2];char Bmp[width*hight*3];//set_bmp_header ((struct bmp_header_t *) BMP, Width, HIGHT);//Initialize Camera init_cameral (WIDTH, HIGHT);//Initialize Framebufferinit_framebuffer (WIDTH, HIGHT); Turn on the camera start_cameral ();//collect a picture int count = 0; while (1) {get_picture (YUYV); Yuyv2rgb24 (YUYV, BMP, WIDTH, HIGHT); Write_framebuffer (BMP);//printf ("count:%d \ n", count++);} Turn off the camera stop_cameral ();//close Framebufferexit_framebuffer ();//exit exit_cameral (); return 0;}
2, Juv.h< /span>
#ifndef __jyuv_h#define __jyuv_htypedef unsigned char u8;typedef unsigned short u16;typedef unsigned int u32;# pragma pack (1)//define BMP head struct bmp_header_t{ U16 Magic; U32 file_size; U32 RESERVED1; U32 offset; The bytes represents 54 offsets of u32 head_num; u32 width; u32 height; U16 Color_planes;//1 U16 Bit_count; U32 bit_compression;//0 u32 image_size;//except the size of the header u32 h_resolution; U32 v_resolution; U32 Color_num; U32
3, JUV.C< /span>
#include "j-yuv.h" #define Bit_count 24void set_bmp_header (struct bmp_header_t *header, u32 width, u32 height) {Header ->magic = 0x4d42; Header->image_size = width * Height * BIT_COUNT/8; Header->file_size = Header->image_size + 54; header->reserved1 = 0; Header->offset = 54; Header->head_num = 40; Header->width = width; Header->height = height; Header->color_planes = 1; Header->bit_count = Bit_count; header->bit_compression = 0; header->h_resolution = 0; header->v_resolution = 0; Header->color_num = 0; header->important_colors = 0;} YUYV rgb24 algorithm realizes int yuyv2rgb24 (U8 *yuyv, U8 *rgb, u32 width, u32 height) {u32 I, in, Rgb_index = 0; U8 y0, u0, Y1, v1; int R, G, B; U32 out = 0, x, y; for (in = 0, in < width * Height * 2, in + = 4) {y0 = Yuyv[in+0];u0 = Yuyv[in+1];y1 = Yuyv[in+2];v1 = Yuyv[in+3];for ( i = 0; I < 2; i++) {if (i) y = Y1;elsey = Y0;r = y + ($ * (v1-128))/100; //rg = y-(u0-128)/100-(* (v1-128))/100; G B = y + (177 * (u0-128))/100; bif (R > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; if (r < 0) R = 0; if (g < 0) g = 0; if (b < 0) b = 0;y = Height-rgb_index/width-1;x = rgb_index%width;rgb[(y*width+x) *3+0] = b;rgb[(y*width+x) *3+1] = g;rgb[(y*width+x) *3+2] = r;rgb_index++;} } return 0;}4, Framebufferopt.c
#include "FrameBufferOpt.h" static int frame_fd; static int *framebuffer = NULL; static int W, H;//Initialize framebufferint init_framebuffer (int Width, int higth) {W = width; H = Higth; FRAME_FD = open ("/DEV/FB", O_RDWR), if ( -1 = = frame_fd) {perror ("Open Frame buffer fail"); return-1;} There's no need for CPU handling. DMA as Porter framebuffer = mmap (0, 1280*1024*4, Prot_read | Prot_write, map_shared, FRAME_FD, 0); if (FrameBuffer = = (void *)-1) {perror ("Memory MAP fail"); return-2;} return 0; }//writes Framebufferint write_framebuffer (const char *buffer) {int row, col; char *p = NULL; for (row = 0; row <1024; R ow++) {for (col = 0; col < 1280; col++) {if ((Row < H) && (Col < W)) {p = (char *) (buffer + (row * w+ Col) * 3); Framebuffer[row*1280+col] = RGB ((unsigned char) (* (p+2)), (unsigned char) (* (p+1)), (unsigned char) (*p));}} return 0; }//exit Framebufferint exit_framebuffer (void) {Munmap (Framebuffer, w*h*4); close (FRAME_FD); return 0;}5.FrameBufferOpt.h
#ifndef _framebufferopt_h#define _framebufferopt_h#include <stdio.h> #include <fcntl.h># Include <unistd.h> #include <sys/mman.h> #define RGB (r,g,b) ((r<<16) | ( G<<8) |b)//Initialize ramebufferint init_framebuffer (int Width, int higth);//write Data to Framebufferint Write_framebuffer ( const char *buffer);//exit Framebufferint exit_framebuffer (void); #endif//_framebufferopt_h
6, CameralOpt.h
#ifndef _cameralopt_h#define _cameralopt_h#include <stdio.h> #include <linux/videodev2.h># Include <fcntl.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include < errno.h> #include <sys/mman.h> #define COUNT 3//Initialize camera int init_cameral (int Width, int Hight); int Exit _cameral (void); Exit Camera//camera start acquisition int start_cameral (void), int stop_cameral (void);//Stop camera//Get Camera Data int get_picture (char *buffer); endif //_cameralopt_h
7.cameralopt.c< /span>
#include "CameralOpt.h" int video_fd; int length; Char *yuv[count]; struct V4l2_buffer enqueue, dequeue; Define the entry and exit team operations struct member int init_cameral (int Width, int Hight) {//parameter check char *videodevname = NULL; videodevname = "/dev/video0";// Open Device video_fd = open (Videodevname, O_RDWR), if ( -1 = = video_fd) {perror ("Open video Device Fail"); return-1;} int i; int ret; struct V4l2_format format; Format.type = v4l2_buf_type_video_capture; Format.fmt.pix.width = width; Format.fmt.pix.height = Hight; Format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; The format I support is this ret = IOCTL (VIDEO_FD, VIDIOC_S_FMT, &format); if (ret! = 0) {perror ("Set video format fail"); return-2;} Apply buffer, cut into several parts//3struct v4l2_requestbuffers requestbuffer; Requestbuffer.count = count; Requestbuffer.type = v4l2_buf_type_video_capture; Requestbuffer.memory = V4l2_memory_mmap; RET = IOCTL (VIDEO_FD, Vidioc_reqbufs, &requestbuffer); if (ret! = 0) {perror ("Request buffer fail"); return-3;} Querybufferstruct V4l2_buffER querybuffer; Querybuffer.type = v4l2_buf_type_video_capture; Querybuffer.memory = V4l2_memory_mmap; for (i = 0; i < COUNT; i++) {querybuffer.index = i; ret = IOCTL (VIDEO_FD, Vidioc_querybuf, &querybuffer); if (ret ! = 0) {perror ("Query buffer Fail"); return-4;} printf ("index:%d length:%d offset:%d \ n",//querybuffer.index, Querybuffer.length, querybuffer.m.offset); length = Qu Erybuffer.length; Print the camera memory to the memory address of the process yuv[i] = mmap (0,querybuffer.length, Prot_read | Prot_write, map_shared, VIDEO_FD, querybuffer.m.offset);//queue struct V4l2_buffer queuebuffer; Queuebuffer.type = v4l2_buf_type_video_capture; Queuebuffer.memory = V4l2_memory_mmap; Queuebuffer.index = i; RET = IOCTL (VIDEO_FD, Vidioc_qbuf, &queuebuffer); if (ret! = 0) {perror ("Queuebuffer fail"); return-5;}} Initialize the queue enqueue.type = v4l2_buf_type_video_capture; Dequeue.type = v4l2_buf_type_video_capture; Enqueue.memory = V4l2_memory_mmap; Dequeue.memory = V4l2_memory_mmap; return 0; }int Exit_cameral (void) {int i; for (i = 0; i < COUNT; i++) Munmap (yuv+i, length); Close (VIDEO_FD); return 0;} int start_cameral (void) {//Turn on camera int ret; int on = 1; ret = IOCTL (VIDEO_FD, Vidioc_streamon, &on); if (ret! = 0) {Perro R ("Start Cameral fail"); return-1; }return 0; }int stop_cameral (void) {//stop camera int ret; int off= 1; ret = IOCTL (VIDEO_FD, Vidioc_streamoff, &off); if (ret! = 0) {Perr or ("Stop cameral Fail"); return-1; }return 0;} int get_picture (char *buffer) {int ret;//out-of-force RET = IOCTL (VIDEO_FD, Vidioc_dqbuf, &dequeue); if (ret! = 0) {perror ("deque UE fail "); return-1; }//get Picture data YUV yuv[dequeue.index]memcpy (buffer, Yuv[dequeue.index], dequeue.length);//write (YUYV_FD, yuv[ Dequeue.index], dequeue.length); enqueue.index = Dequeue.index; RET = IOCTL (VIDEO_FD, Vidioc_qbuf, &enqueue); if (ret! = 0) {perror ("enqueue fail"); return-2;} return 0; }
Running result: Landlord himself, ugly don't spray. The picture is actually always moving, but I took a picture just.
C Language Advanced application---operating Linux under V4L2 camera app