V4L2 Video acquisition and H264 encoding 2-V4L2 acquisition YUV Data __ Encoding

Source: Internet
Author: User
Tags assert printf

In the previous article because the USB camera used on the PC can only support Gpeg image format, but the H264 encoding needs to use YUV data, so I found an arm development board to do the test. This thought that the code from the PC to the Development Board is a very simple thing, who knows that because the platform or v4l2 the difference between the bottom of the drive, and finally spent the Dickens to solve the problem. Words not much to say, directly on the code:

/*============================================================================= # filename:v4l2.c # Desc:thi
S program Aim-get image from USB camera, # used the V4l2 interface. # Author:licaibiao # Version: # lastchange:2016-12-10 # History: ================================== ===========================================*/#include <unistd.h> #include <sys/types.h> #include < sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <sys/ioctl.h> #include <stdlib.h > #include <linux/types.h> #include <linux/videodev2.h> #include <malloc.h> #include <math.h > #include <string.h> #include <sys/mman.h> #include <errno.h> #include <assert.h> #define FI
	Le_video "/dev/video0" #define JPG "./out/image%d" typedef struct{void *start;
int length;

}buftype;
Buftype *usr_buf;


static unsigned int n_buffer = 0; /*set Video Capture Ways (mmap) */INT init_mmap (int fd) {/*to request frame cache, contain requested counts*/struct v4l2_requestbuffers reqbufs;
	memset (&reqbufs, 0, sizeof (REQBUFS)); 	 							Reqbufs.count = 1;    
	/*the number of buffer*/reqbufs.type = v4l2_buf_type_video_capture;				

	Reqbufs.memory = V4l2_memory_mmap;
		if ( -1 = = IOCTL (FD,VIDIOC_REQBUFS,&AMP;REQBUFS)) {perror ("Fail to ioctl ' Vidioc_reqbufs '");
	Exit (Exit_failure);
	} n_buffer = Reqbufs.count;
	printf ("N_buffer =%d\n", n_buffer);
	Usr_buf = calloc (reqbufs.count, sizeof (USR_BUF));
	Usr_buf = calloc (reqbufs.count, sizeof (Buftype));
		if (usr_buf = = NULL) {printf ("Out of memory\n");
	Exit (-1); }/*map kernel cache to user process*/for (n_buffer = 0; N_buffer < Reqbufs.count; ++n_buffer) {//stand for a FR
		Ame struct V4l2_buffer buf;
		memset (&buf, 0, sizeof (BUF));
		Buf.type = v4l2_buf_type_video_capture;
		Buf.memory = V4l2_memory_mmap;
		
		Buf.index = N_buffer; /*check the information of the kernel cache requested*/
		if ( -1 = = IOCTL (fd,vidioc_querybuf,&buf)) {perror ("Fail to Ioctl:vidioc_querybuf");
		Exit (Exit_failure);
		} usr_buf[n_buffer].length = Buf.length; Usr_buf[n_buffer].start = (char *) mmap (Null,buf.length,prot_read |

		Prot_write,map_shared, Fd,buf.m.offset);
			if (map_failed = = Usr_buf[n_buffer].start) {perror ("Fail to Mmap");
		Exit (Exit_failure);
	}}} int Open_camera (void) {int fd;

	struct V4l2_input inp; FD = open (File_video, O_RDWR |
	o_nonblock,0);
		if (FD < 0) {fprintf (stderr, "%s open err \ n", File_video);
	Exit (Exit_failure);

	};
	Inp.index = 0;
	if ( -1 = = IOCTL (FD, Vidioc_s_input, &AMP;INP)) {fprintf (stderr, "Vidioc_s_input \ n");
} return FD; 		} int Init_camera (int fd) {struct v4l2_capability cap;/* decive fuction, such as video input */struct V4L2_FORMAT TV_FMT;  	/* Frame format */struct V4L2_FMTDESC fmtdesc;
	/* Detail Control value */struct V4l2_control ctrl;
	
			int ret;
	/*show all the support format*/memset (&fmtdesc, 0, sizeof (FMTDESC));                 Fmtdesc.index = 0;

	/* The number to check */fmtdesc.type=v4l2_buf_type_video_capture; /* Check video decive driver capability */if (Ret=ioctl (FD, Vidioc_querycap, &cap) <0) {fprintf (stderr, "Fail t
		o ioctl video_querycap \ n ");
	Exit (Exit_failure); }/*judge Wherher or not to be a video-get device*/if (! ( Cap.capabilities & V4l2_buf_type_video_capture) {fprintf (stderr, "The current device was not a VIDEO CAPTURE Devic
		e \ n ");
	Exit (Exit_failure); }/*judge whether or not to supply the form of video stream*/if (! (
		Cap.capabilities & v4l2_cap_streaming) {printf ("The current device does is not a support streaming i/o\n");
	Exit (Exit_failure);
	} printf ("\ncamera driver name is:%s\n", cap.driver);
	printf ("Camera device name is:%s\n", Cap.card);

	printf ("Camera Bus Information:%s\n", cap.bus_info);
	/*display The format device support*/printf ("\ n"); while (IOCTL (FD,VIDIOC_ENUM_FMT,&AMP;FMTDESC) {!=-1) {printf ("Support Device%d.%s\n", fmtdesc.index+1,fmtdesc.description);
	fmtdesc.index++;

	} printf ("\ n");      /*set the form of camera capture data*/tv_fmt.type = v4l2_buf_type_video_capture;
	/*v4l2_buf_typea,camera must use v4l2_buf_type_video_capture*/tv_fmt.fmt.pix.width = 680;
	Tv_fmt.fmt.pix.height = 480;	Tv_fmt.fmt.pix.pixelformat = v4l2_pix_fmt_yuv420;   		/*v4l2_pix_fmt_yyuv*/Tv_fmt.fmt.pix.field = V4l2_field_none;
		/*v4l2_field_none*/if (IOCTL (FD, VIDIOC_S_FMT, &tv_fmt) < 0) {fprintf (stderr, "vidioc_s_fmt set err\n");
		Exit (-1);
	Close (FD);
} init_mmap (FD);
	} int start_capture (int fd) {unsigned int i;
	
	Enum V4l2_buf_type type;
		/*place the kernel cache to a queue*/for (i = 0; i < N_buffer; i++) {struct V4l2_buffer buf;
		memset (&buf, 0, sizeof (BUF));
		Buf.type = v4l2_buf_type_video_capture;
		Buf.memory = V4l2_memory_mmap;

		Buf.index = i; if ( -1 = = IOCTL (FD, VIDIOC_QBUF, &buf)) {perror ("Fail to IOCTL" VIdioc_qbuf ' ");
		Exit (Exit_failure);
	}} type = V4l2_buf_type_video_capture;
		if ( -1 = = IOCTL (FD, Vidioc_streamon, &type)) {printf ("i=%d.\n", I);
		Perror ("Vidioc_streamon");
		Close (FD);
	Exit (Exit_failure);
} return 0;

	} int process_image (void *addr, int length) {FILE *fp;

	static int num = 0;
	Char image_name[20];
	sprintf (Image_name, JPG, num++);
		if (fp = fopen (Image_name, "w")) = = NULL) {perror ("Fail to fopen");
	Exit (Exit_failure);
	} fwrite (addr, length, 1, FP);
	Usleep (500);
	Fclose (FP);
return 0;
	} int read_frame (int fd) {struct V4l2_buffer buf;
	unsigned int i;
	memset (&buf, 0, sizeof (BUF));
	Buf.type = v4l2_buf_type_video_capture;
	Buf.memory = V4l2_memory_mmap;
		Put cache from Queue if ( -1 = = IOCTL (FD, VIDIOC_DQBUF,&AMP;BUF)) {perror ("Fail to ioctl ' vidioc_dqbuf '");
	Exit (Exit_failure);

	} assert (Buf.index < n_buffer); Read process space ' s data to a file Process_image (Usr_buf[buf.index].start, usr_buf[buf.index].length);
	if ( -1 = = IOCTL (FD, VIDIOC_QBUF,&AMP;BUF)) {perror ("Fail to ioctl ' vidioc_qbuf '");
	Exit (Exit_failure);
} return 1;
	} int mainloop (int fd) {int count = 10;
		while (count--> 0) {for (;;)
			{Fd_set FDS;
			struct Timeval TV;

			int R;
			Fd_zero (&fds);

			Fd_set (Fd,&fds);
			/*timeout*/tv.tv_sec = 2;
			tv.tv_usec = 0;
			
			R = Select (FD + 1,&AMP;FDS,NULL,NULL,&AMP;TV);
				if ( -1 = = r) {if (eintr = = errno) continue;
				Perror ("Fail to select");
			Exit (Exit_failure);
				} if (0 = = r) {fprintf (stderr, "select timeout\n");
			Exit (-1);
		} if (Read_frame (FD)) break;
}} return 0;
	} void Stop_capture (int fd) {enum V4l2_buf_type type;
	Type = V4l2_buf_type_video_capture;
		if ( -1 = = IOCTL (fd,vidioc_streamoff,&type)) {perror ("Fail to ioctl ' Vidioc_streamoff '");
	Exit (Exit_failure);
	}} void Close_camera_device (int fd) {unsigned int i; for (i = 0;i < N_buffer; i++) {if ( -1 = = Munmap (usr_buf[i].start,usR_buf[i].length)) {exit (-1);

	}} free (USR_BUF);
		if ( -1 = = Close (FD)) {perror ("Fail to close FD");
	Exit (Exit_failure);
	}} void Main (void) {int fd;
	FD = Open_camera ();
	Init_camera (FD);
	Start_capture (FD);
	Mainloop (FD);
	Stop_capture (FD);
Close_camera_device (FD);

 }
The code is ported from the code of the previous chapter, mainly for my board transplant, mainly modified:

(1) Camera open changed by blocking open to non-blocking mode

(2) Mmap changed from the original map_private mode to map_shared Way

(3) Imag format changed from original v4l2_pix_fmt_jpeg to v4l2_pix_fmt_yuv420

(4) In my Development Board, the index number of the camera device must be set, i.e. the IOCTL (FD, Vidioc_s_input, &INP) in the above code, with a value of Inp.index = 0; If not set, a select timeout problem occurs when select.

Cross-compile the above code and put it on the board to run, the result is as follows:

/tmp #./test Camera driver name is:sunxi-vfe camera device name Is:sunxi-vfe camera bus Information:sunxi_vfe vfe.  2 Support Device 1.planar YUV 422 support device 2.planar YUV 420 support device 3.planar YVU 420 support device 4.planar YUV 422 UV Combined support device 5.planar YUV 420 UV Combined support device 6.planar YUV 422 VU combined Support Devic E 7.planar YUV 420 VU combined support device 8.MB YUV420 support device 9.yuv422 YUYV support device 10.yuv422 Yvyu Suppo RT device 11.yuv422 UYVY support device 12.yuv422 Vyuy support device 13.RAW Bayer BGGR 8bit support device 14.RAW Bayer G BRG 8bit Support Device 15.RAW Bayer GRBG 8bit support device 16.RAW Bayer RGGB 8bit support device 17.RAW Bayer Bggr 10bi T support device 18.RAW Bayer GBRG 10bit support device 19.RAW Bayer GRBG 10bit support device 20.RAW Bayer RGGB 10bit sup Port device 21.RAW Bayer bggr 12bit support device 22.RAW Bayer GBRG 12bit support device 23.RAW Bayer GRBG 12bit Support Device 24.RAW Bayer RGGB 12bit n_buffer = 3/tmp # ls HOSTAPD messages out Test utmp/tmp # cd out/tmp/out # ls image0 image2 im        Age4 image6 image8 image1 image3 image5 image7 image9/tmp/out # ls-l Total 4520-rw-r--r--1 root root 460800 Jan 1 00:01 image0-rw-r--r--1 root root 460800 Jan 1 00:01 image1-rw-r--r--1 root Roo     T 460800 Jan 1 00:01 image2-rw-r--r--1 root root 460800 Jan 1 00:01 image3-rw-r--r--1 root Root 460800 Jan 1 00:01 image4-rw-r--r--1 root root 460800 Jan 1 00:01 image5-rw-r--r--1     root root 460800 Jan 1 00:01 image6-rw-r--r--1 root root 460800 Jan 1 00:01 image7-rw-r--r-- 1 root root 460800 Jan 1 00:01 image8-rw-r--r--1 root root 460800 Jan 1 00:01 image9/tmp  /OUT #
From the information we output can be seen, in my Development Board can support 24 image format, in this we H264 behind the code, where the use of the v4l2_pix_fmt_yuv420 format. My development Board is mounted on the GC0308 VGA camera, from the size of the generated image can be judged to be correct (YUV420 data size = long * Width * 1.5 = 640 * 480 * 1.5 = 460800 = 450k)

Image files can be copied out, using PYUV software to view YUV pictures. It is important to note that when using PYUV to view YUV pictures, you need to set the image format correctly, according to the data format collected by my code, it is set as follows:


The picture shown for normal open is:


The acquisition of YUV data here is over, and the next chapter describes the use of the X264 library to encode YUV data into H264 video files.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.