Ubuntu captures JPG via v4l2 and displays JPG

Source: Internet
Author: User
Tags printf

With Ubuntu want to write code, at any time to observe the state behind their own, with cheese do the video is too obvious, but also have to move the mouse, to write a camera with the tool to take pictures. It should be easiest to use V4L2.

header files, including Mem,dev and IOCTL-related header files

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ Mman.h>
#include <linux/videodev2.h>

Define a structure that is easy to pass

struct buffer
{
	void* start;
	unsigned int length;
};

All the function definitions:

int main () {file* fp;
	int fd_video;

	struct buffer *buffers;
	Turn on the camera device Fd_video = open ("/dev/video0", O_RDWR);
		if (Fd_video < 0) {perror ("video capture Open");
	return fd_video;
	} fp = fopen ("/root/test.jpg", "wb+");
		if (FP < 0) {perror ("FB open error.");
	return-1;
	}//Print supported video formats for struct V4L2_FMTDESC fmtdesc;
	fmtdesc.index=0;
	Fmtdesc.type=v4l2_buf_type_video_capture;
	printf ("Support format:\n"); while (IOCTL (Fd_video, VIDIOC_ENUM_FMT, &fmtdesc)! =-1) {printf ("\t%d.%s, fmtdesc:%d\n", Fmtdesc.index+1,
		Fmtdesc.description,fmtdesc.pixelformat);
	fmtdesc.index++;
	}//Set the format of the video, 720P JPEG struct V4l2_format s_fmt;
	S_fmt.fmt.pix.width = 1280;
	S_fmt.fmt.pix.height = 720;
	S_fmt.fmt.pix.pixelformat = V4l2_pix_fmt_mjpeg;
	printf ("s_fmt.fmt.pix.pixelformat:%d\n", S_fmt.fmt.pix.pixelformat);
	S_fmt.type = v4l2_buf_type_video_capture;
	int flag= IOCTL (FD_VIDEO,VIDIOC_S_FMT,&AMP;S_FMT);
		if (flag! = 0) {printf ("Set format error\n");
	return-1; } priNTF ("jpeg:%d%d\n", s_fmt.fmt.pix.width,s_fmt.fmt.pix.height);
	Apply 1 buffers of struct v4l2_requestbuffers req;
	Req.count=1;
	Req.type=v4l2_buf_type_video_capture;
	Req.memory=v4l2_memory_mmap;
	IOCTL (FD_VIDEO,VIDIOC_REQBUFS,&AMP;REQ);
	Buffer associated with application//application 1 struct buffer space buffers = (struct buffer*) calloc (req.count, sizeof (struct buffer));
		if (!buffers) {perror ("Out of Memory");
	Exit (Exit_failure);
	} unsigned int n_buffers;
		for (n_buffers = 0; n_buffers < Req.count; n_buffers++) {struct V4l2_buffer buf;
		memset (&buf,0,sizeof (BUF));
		Buf.type = v4l2_buf_type_video_capture;
		Buf.memory = V4l2_memory_mmap;
		Buf.index = n_buffers;
		if ( -1 = = IOCTL (Fd_video, Vidioc_querybuf, &buf)) exit (-1);
		Buffers[n_buffers].length = Buf.length; Buffers[n_buffers].start = Mmap (NULL, Buf.length,prot_read |
		Prot_write, Map_shared,fd_video, Buf.m.offset);
	if (map_failed = = Buffers[n_buffers].start) exit (-1);
	} enum V4l2_buf_type type; for (n_buffers = 0; n_buffers < Req.count;
		n_buffers++) {struct V4l2_buffer buf;
		Buf.type = v4l2_buf_type_video_capture;
		Buf.memory = V4l2_memory_mmap;
		Buf.index = n_buffers;
	IOCTL (Fd_video, Vidioc_qbuf, &buf);
	}//Start capturing image type = V4l2_buf_type_video_capture;


	IOCTL (Fd_video, Vidioc_streamon, &type);
	struct V4l2_buffer buf;
	memset (& (BUF), 0, sizeof (BUF));
	Buf.type = v4l2_buf_type_video_capture;
	Buf.memory = V4l2_memory_mmap;
	Remove image Data ioctl (Fd_video, Vidioc_dqbuf, &buf);
	Save Image Fwrite (BUFFERS[BUF.INDEX].START,1,BUFFERS[BUF.INDEX].LENGTH,FP);//mjpeg fflush (FP);

	Put back the buffer ioctl (FD_VIDEO,VIDIOC_QBUF,&AMP;BUF); 
	for (n_buffers = 0; n_buffers < req.count; n_buffers++) Munmap (Buffers[n_buffers].start, buffers[n_buffers].length);

	Free (buffers);
	Close (Fd_video);
	Fclose (FP); printf ("Capture jpg finish.
        \ n ");
System ("Eog-w/root/test.jpg &");  }

Description

Turn on the camera and picture

Fd_video = open ("/dev/video0", O_RDWR);
fp = fopen ("/root/test.jpg", "wb+");

Query webcam supported formats, my computer supports YUYV and MJPEG

IOCTL (Fd_video, VIDIOC_ENUM_FMT, &fmtdesc)

Set the format of the camera shot, the size is 720P, the format is MJPEG

IOCTL (FD_VIDEO,VIDIOC_S_FMT,&S_FMT)

Request buffer, a picture will need a frame of buffer

IOCTL (FD_VIDEO,VIDIOC_REQBUFS,&REQ);
Using Calloc is to apply for multiple buffers, here to apply for 1 buffers, like malloc, here is the camera based on the change, with calloc will not change.

buffers = (struct buffer*) calloc (req.count, sizeof (struct buffer));
The purpose of mapping memory with MMAP is to eliminate the expense of memcpy, more reasonable

Buffers[n_buffers].start = Mmap (NULL,
				buf.length,prot_read | Prot_write, Map_shared,fd_video, Buf.m.offset);
Set the buffer and put it back in the buffer

IOCTL (Fd_video, VIDIOC_QBUF, &buf)
Start capturing images

IOCTL (Fd_video, Vidioc_streamon, &type)
Remove a frame of data from the buffer
IOCTL (Fd_video, VIDIOC_DQBUF, &buf)
Take the data and put it back in the buffer
IOCTL (Fd_video, VIDIOC_QBUF, &buf)

After releasing the resources, we will not repeat them.

The JPG is displayed by the eye of Gnome.

System ("Eog-w/root/test.jpg &");


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.