Implementing video Reading under Linux

Source: Internet
Author: User
Tags goto

V4L (Video4linux is the basis of some video systems, video software, audio software, often in the need to capture images of the occasion, such as video surveillance, webcam, videophone, often
Using the system interface that is often used in Linux embedded development in embedded Linux. It is the programming interface that the Linux kernel provides to the user space, all kinds of video and audio equipment open
After the corresponding driver, you can control the video and audio equipment through the system API provided by V4L, that is to say, v4l is divided into two layers, the bottom is the driver of the audio and video device in the kernel, on
Layer is a system-provided API, and what is needed for us is the use of these system APIs.
V4L2 is an upgraded version of V4L, which provides a set of interface specifications for Linux under the video device program. Includes a set of data structures and the underlying V4L2 driver interface. V4l2 in a pipeline way,
Simple and intuitive operation, basically follow the open video device, format, processing data, turn off the device, more specific operations through the IOCTL function to achieve.

1, open device
int open (const char *device_name, int flags);
int fd = open ("/dev/video0", o_rdonly); O_nonblock-Non-blocking (deprecated)
2, close device int close (int fd)
int ret = close (FD);
  3. V4l2_capability View Property
int fd, int request, struct v4l2_capability *argp);
struct v4l2_capability
{
U8 driver[16];//driver name
U8 CARD[32];//device name
U8 bus_info[32];//equipment in the system Location
U32 version;//driver build number
U32 capabilities;//device supported Operation
U32 reserved[4];//reserved field
};

4, set video format and standard
related functions:
int IOCTL (int fd, int request, struct v4l2_fmtdesc *argp);
int ioctl (int fd, int request, struct v4l2_format *argp);

Related structure:
The V4L2_CROPCAP structure is used to set the capture capability of the camera, the Type field of the
V4l2_cropcap should be set first when capturing the video, and then the parameters of the device capture capability are obtained through the VIDIO_CROPCAP operation command. Saved in the V4L2_CROPCAP structure, including the bounds
(the upper-left coordinate and the width height of the maximum snap box), Defrect (the upper-left coordinate and width height of the default snap box), and so on.
V4l2_format structure to set the camera's video format, frame formats, etc., when setting this parameter should first fill in the V4l2_format of the various fields, such as type (transport stream type),
Fmt.pix.width (wide), Fmt.pix.heigth (High), Fmt.pix.field (sampling area, such as interlaced sampling), Fmt.pix.pixelformat (sampling type, such as Yuv4:2:2),
and then vidio_s_fmt The action command sets the video capture format.
struct V4l2_fmtdesc
{
U32 index;//format ordinal to query, application settings
enum V4l2_buf_type type;//frame type, application settings
U32 flags; is the compressed format
U8 description[32];//format name
U32 pixelformat;//Format
U32 reserved[4];//Reserved
};
All video formats can be viewed in the following ways
#define V4L2_FOURCC (A, B, C, D) ((a) | ((b) << 8) | ((c) << 16) | ((d) <<))
All format:vidioc_enum_fmt, V4l2_fmtdesc

struct V4l2_format
{
Enum V4l2_buf_type type; Frame type, application settings
Union FMT
{
struct V4l2_pix_format pix; Video Device usage
struct V4l2_window win;
struct V4l2_vbi_format vbi;
struct V4l2_sliced_vbi_format sliced;
U8 raw_data[200];
};
};

struct V4l2_pix_format
{
U32 width; Frame width, per pixel
U32 height; Frame height, per pixel
U32 PixelFormat; Frame format
enum V4l2_field field;
U32 Bytesperline;
U32 Sizeimage;
Enum V4l2_colorspace ColorSpace;
U32 Priv;
};

5. Viewing the video frame rate
int ioctl (int fd, int request, struct v4l2_streamparm parm* argp);
struct V4l2_streamparm parm;
Parm.type = v4l2_buf_type_video_capture;
Where Vidioc_g_parm is used to frame rate, vidioc_s_parm is used to set the frame rate

6. Custom IOCTL function
Find the Kernel/include/linux/videodev2.h header file in the kernel directory, you can view all the commands of IO control
/*
*experimental, third param 0--video, 1--tracking
*/
#define Vidioc_poccess_notify _iow (' V ', (), int)//add by Henry.wen 20131126

Instance:

#ifndef camera_v4l2camera_h#define camera_v4l2camera_h#include <stdio.h> #include <stdlib.h> #include               <string.h> #include <assert.h> #include <getopt.h>/* Getopt_long () */#include <fcntl.h> /* Low-level I/o */#include <unistd.h> #include <errno.h> #include <malloc.h> #include <sy s/stat.h> #include <sys/types.h> #include <sys/time.h> #include <sys/mman.h> #include <sys/ ioctl.h> #include <asm/types.h> * for videodev2.h * * #include <linux/videodev2.h> #define Config_cam era_uvc_inval_framecnt 5namespace v4l2{/** * return error code */enum _ret_error_code{ret_error_fail = -1,RET_ERROR_OK = 0,ret_error_capture_null = -9999,ret_error_capture_name,ret_error_capture_capability,ret_error_capture_format, Ret_error_capture_buffer,ret_error_capture_outmemory,ret_error_capture_mmap,ret_error_capture_form,ret_error_ capture_mumap,ret_error_capture_vidioc,};/** * Name:video_format Enum * Function:describe formats V4L2 would support */typedef enum _pformat{unknown,yuyv,mjpeg,yv12,yu12,nv12,nv21,h264,}  pformat;/** * Frame width and height infomation */typedef struct _v4l2info{unsigned int width;unsigned int height;unsigned int stepwidth;unsigned int length;void* buffer;          v4l2info;/** * caputre Properties */typedef struct _v4l2capture{pformat Format;char name[31];//dev_nameint fd;unsigned int rate;unsigned int quality;unsigned int brightness; V4l2info V4l2info;} v4l2capture;/** * */class V4l2camera{public:v4l2camera (); virtual ~v4l2camera ();p ublic:/** * Get the number of cameras * * @return the number of camera */static int Getnumberofcameras ();/** * Initialize V4L2 device * @param capture V4L2 Capture Handl * @param width frame width * @param height fram Height * * @return 0/other successful or failure */int Initdevice (V4 L2capture *capture, pformat format, const char* name, unsigned int rate, unsigned int width, unsigned int height);/** * Initialize V4L2 device * @param capture V4L2 Capture Handl * @param width frame width * @param height fram Height * * @ Return 0/other successful or failure */int Uninitdevice (v4l2capture *capture);/** * Set v4l2 Device brightness * @param CA Pture v4l2 Capture Handl * @param value Brightness value * * @return 0/other successful or failure */int setbrightness (v4l 2Capture *capture, unsigned int value);/** * Start v4l2 device * @param fd V4L2 Capture Handl * * @return 0/other SUCCESSF UL or failure */int startdevice (int fd)/** * Stop V4L2 device * @fd capture V4L2 capture Handl * * @return 0/other succes Sful or failure */int stopdevice (int fd);/** * Get frame data * @param capture V4L2 capture Handl * * @return 0/other SUCC Essful or failure */int getframe (v4l2capture *capture);p rivate:int initmmap (int fd); int xioctl (int fd, int request, void * arg); unsigned int getcameraformat (pformat format); int adjustv4l2info (unsigned int& width, unsigned int& height) ; int msleep (int fd, Unsigned int msec); int matchcameraauto (int cameraid);p rivate:typedef struct _buffers{void *start;size_t length;} V4l2buffers;int M_stime; v4l2buffers* m_buffers;unsigned int m_nbuffers;  v4l2capture* m_capture;static int mnumberofcameras;static int Mcameraindex[10];int Musbcameraivalidframecnt;bool M_initdevice;};} End Namespace#endif//camera_v4l2camera_h

V4l2Camera.cpp

#include "V4l2Camera.h" namespace v4l2{#define Buffers_count 4#define Array_len (a) (sizeof (a)/sizeof (a[0])) #define Memst_value (x) memset (& (x), 0, sizeof (x)) const V4l2info g_v4l2info[] = {{160, 120}, {320, 240}, {640, 480}, {1024, 76 8}, {1200, 900}, {1440, 1080}, {1600, 900}, {1600, 1200}}; V4l2camera::v4l2camera () {//TODO auto-generated constructor stubm_capture = null;musbcameraivalidframecnt = 0;m_ Initdevice = false;} V4l2camera::~v4l2camera () {//TODO auto-generated destructor stubif (m_capture) Uninitdevice (m_capture);} int v4l2camera::xioctl (int fd, int request, void *arg) {int r;int ncount= 0;do{r = IOCTL (FD, request, ARG);} while (Ret_error_fail = = r && (eintr = = errno) && (++ncount <)); return r;} int v4l2camera::mnumberofcameras = 0;int v4l2camera::mcameraindex[] = {0};unsigned int v4l2camera::getcameraformat ( Pformat format) {unsigned int ret = unknown;switch (format) {case Yuyv:ret = v4l2_pix_fmt_yuyv;break;case Mjpeg:ret = v4l2_p Ix_fmt_mjpeg;break;case YV12: ret = v4l2_pix_fmt_yvu420;break;case Yu12:ret = v4l2_pix_fmt_yuv420;break;case Nv12:ret = V4L2_PIX_FMT_NV12;break; Case Nv21:ret = v4l2_pix_fmt_nv21;break;case H264:ret = v4l2_pix_fmt_mpeg;break;default:break;} return ret;} int v4l2camera::initmmap (int fd) {int ret = ret_error_ok;struct v4l2_requestbuffers req;req.count = Buffers_count; Req.type = V4l2_buf_type_video_capture;req.memory = v4l2_memory_mmap;if (Ret_error_fail = = Xioctl (FD, VIDIOC_REQBUFS, & Amp;req) | | Req.count < 2) {return ret_error_capture_buffer;} M_buffers = (v4l2buffers*) calloc (req.count, sizeof (v4l2buffers)), if (!m_buffers) {return ret_error_capture_outmemory ;} for (m_nbuffers = 0; m_nbuffers < Req.count; ++m_nbuffers) {struct V4l2_buffer buf; Memst_value (BUF); buf.type = V4l2_buf_type_video_capture;buf.memory = V4l2_memory_mmap;buf.index = M_nBuffers;if (RET_ Error_fail = = Xioctl (FD, VIDIOC_QUERYBUF, &buf)) {ret = Ret_error_capture_buffer;break;} M_buffers[m_nbuffers].length = Buf.length;m_buffers[m_nbuffers].start= Mmap (NULL, buf.length, Prot_read | Prot_write, map_shared, FD, Buf.m.offset); if (map_failed = = M_buffers[m_nbuffers].start) {ret = Ret_error_capture_mmap; Break;}} return ret;} int V4l2camera::adjustv4l2info (unsigned int& width, unsigned int& height) {int ret = Ret_error_fail;int index = 0;f or (int ncount = Array_len (g_v4l2info)-1, i = ncount; I >= 0; i) {if (width <= (g_v4l2info[i].width +)) {index = I;ret = RET_ERROR_OK;} else if (0! = ncount) {width = G_v4l2info[index].width;height = G_v4l2info[index].height;break;}} return ret;} int V4l2camera::getnumberofcameras () {char Cam_path[20];int fd =-1, i=0;struct v4l2_capability capability; Mnumberofcameras = 0;memset (mcameraindex,0x00,sizeof (Mcameraindex)); for (i = 0; i < ++i) {memset (cam_path,0x00,20 ); sprintf (Cam_path, "/dev/video%d", i); fd = open (Cam_path, o_rdonly); if (FD < 0) Continue;memset (&capability, 0, sizeof (struct v4l2_capability)); if (IOCTL (FD, VIDIOC_QUERYCAP, &capability) < 0) {//loge ("Video device(%s): query capability not supported.\n ", cam_path); goto loop_continue;} if (capability.capabilities& (V4l2_cap_video_capture | v4l2_cap_streaming)! = (V4l2_cap_video_capture | v4l2_cap_streaming)) {}else{mcameraindex[mnumberofcameras] = i;mnumberofcameras++;} Loop_continue:if (FD > 0) {close (FD); fd =-1;} Continue;} return Mnumberofcameras;} int V4l2camera::matchcameraauto (int cameraid) {if (mnumberofcameras <= 0 | | Mnumberofcameras > | | Cameraid < 0) {return-1;} Search for Camera ID normallyfor (int i = 0; i < Mnumberofcameras; ++i) {if (Cameraid = = Mcameraindex[i]) {return came RaId;}} if (Mnumberofcameras = = 1) {return mcameraindex[0];} return cameraid > Mcameraindex[mnumberofcameras-1]? MCAMERAINDEX[MNUMBEROFCAMERAS-1]: mcameraindex[0];} int V4l2camera::initdevice (v4l2capture *capture, pformat format, const char* name, unsigned int rate, unsigned int width, unsigned int height) {//TODO auto-generated function stubstruct stat st;int FD = 0, Nrealcameranamelen = 0,Nmincameranamelen = 0;int ret = Ret_error_ok;char szcameraid[4], szcameraname[20];int cameraid = 0;struct v4l2_capability Cap;struct v4l2_cropcap cropcap;struct v4l2_crop crop;if (NULL = = Capture | | NULL = = Name | | 0 = = Rate | | 0 = = Width | | 0 = = height) {ret = Ret_error_capture_null;goto initdevicefailed;} if (Nrealcameranamelen = strlen (name)) < (Nmincameranamelen =strlen ("/dev/video0")) {ret = Ret_error_capture_null; Goto initdevicefailed;} Get camera Idmemset (szcameraid,0x00,4), for (int i=0;i<3;i++) {if (Nrealcameranamelen >= (Nmincameranamelen + i)) Szcameraid[i] = name[nmincameranamelen-1 + i];} Cameraid = Atoi (szcameraid); Mnumberofcameras = 0;memset (Mcameraindex, 0x00, sizeof (Mcameraindex)); if (0 = = Getnumberofcameras ()) {//loge ("There is NO camera!"); ret = Ret_error_capture_name;goto initdevicefailed;} if ( -1 = = (Cameraid = Matchcameraauto (cameraid))) {//loge ("There is NO camera!"); ret = Ret_error_capture_name;goto initdevicefailed;} memset (Szcameraname, 0x00, Sprin);TF (Szcameraname, "/dev/video%d", Cameraid);//logi ("Camera name is%s.", name);//if ((Ret_error_fail = = Stat ( Szcameraname, &st)) | | (! S_ISCHR (st.st_mode)) | | (Ret_error_fail = = (FD = open (Szcameraname, O_RDWR | O_nonblock, 0))) {ret = Ret_error_capture_name;goto initdevicefailed;} if (Ret_error_fail = = Xioctl (FD, Vidioc_querycap, &cap) | |! ( Cap.capabilities & v4l2_cap_video_capture) | | ! (Cap.capabilities & V4l2_cap_streaming)) {ret = Ret_error_capture_capability;goto initdevicefailed;} Memst_value (cropcap); cropcap.type = v4l2_buf_type_video_capture;if (Ret_error_ok = Xioctl (FD, VIDIOC_CROPCAP, & CROPCAP) {Crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;CROP.C = cropcap.defrect;/* Reset to Default */xioctl (FD, Vidioc_s_ CROP, &crop);} struct V4l2_format fmt; Memst_value (FMT); ret = Getcameraformat (format); if (UNKNOWN = = ret) {return Ret_error_capture_format;goto initdevicefailed;} if (RET_ERROR_OK! = Adjustv4l2info (width, height)) {RET = Ret_error_capture_form;goto initdevicefaileD;}       Setbrightness (capture, capture->brightness); fmt.type = V4l2_buf_type_video_capture;fmt.fmt.pix.width = Width;fmt.fmt.pix.height = Height;fmt.fmt.pix.pixelformat = Ret;fmt.fmt.pix.field = V4L2_FIELD_INTERLACE D;printf ("%s (%d) pixel format is%d\n", __function__,__line__,ret); if (Ret_error_fail = = Xioctl (FD, VIDIOC_S_FMT, &f MT)) {ret = Ret_error_capture_format;goto initdevicefailed;} if (RET_ERROR_OK! = (RET = Initmmap (FD))) {//| | | Ret_error_ok! = (ret = setbrightness (Capture, capture->brightness))) goto initdevicefailed; Set Video frame ratestruct v4l2_streamparm parm;parm.type = v4l2_buf_type_video_capture;if (RET_ERROR_OK! = IOCTL (FD, V Idioc_g_parm, &parm) {//logi ("Vidioc_g_parm fail ...");} Parm.parm.capture.timeperframe.numerator = 1;parm.parm.capture.timeperframe.denominator = Rate;if (RET_ERROR_OK! = IOCTL (FD, Vidioc_s_parm, &parm)) {//logi ("Vidioc_s_parm Fail ..."); Check setting of Frame Ratememset (&parm, 0x00, SizeoF (v4l2_streamparm));p Arm.type = V4l2_buf_type_video_capture;ret = IOCTL (FD, Vidioc_g_parm, &parm); if (ret! = RET_ ERROR_OK) {//logi ("Vidioc_g_parm fail ..."); CAPTURE-&GT;FD = Fd;capture->v4l2info.width = Fmt.fmt.pix.width;capture->v4l2info.height = Fmt.fmt.pix.height; Capture->format = Format;capture->rate = Rate;capture->v4l2info.length = fmt.fmt.pix.sizeimage;capture-> V4l2info.stepwidth = Fmt.fmt.pix.bytesperline;capture->v4l2info.buffer = malloc (fmt.fmt.pix.sizeimage); strncpy ( Capture->name, name, sizeof (capture->name)) M_stime = 1000/rate;m_capture = Capture;m_initdevice = True;return RE T;initdevicefailed:if (FD >= 0) {close (FD); fd =-1;} return ret;} int V4l2camera::uninitdevice (v4l2capture *capture) {//TODO auto-generated function stubprintf ("%s (%d) ... [begin]\n ", __function__, __line__); int ret = RET_ERROR_OK;IF (!m_initdevice) {return ret;} else {m_initdevice = false;} if (m_buffers) {for (unsigned int i = 0; i < m_nbuffers; ++i) {printf ("%s (%d)Munmap () i =%d\n ", __function__, __line__, i); if (Ret_error_fail = = Munmap (M_buffers[i].start, M_buffers[i].length)) {RE t = Ret_error_capture_mumap;break;}} if (RET_ERROR_OK = = RET) {printf ("%s (%d) free (m_buffers) \ n", __function__, __line__); free (m_buffers);} M_buffers = null;if (Capture) {if (Capture->v4l2info.buffer) {printf ("%s (%d) free (capture->v4l2info.buffer) \ n", __FUNCTION__,__LINE__); free (capture->v4l2info.buffer); capture->v4l2info.buffer = NULL;} if (capture->fd >= 0) {printf ("%s (%d) close (CAPTURE-&GT;FD) \ n", __function__, __line__); ret = Close (capture-> FD);}}} printf ("%s (%d) ... [end]\n ", __function__, __line__); return ret;} int v4l2camera::setbrightness (v4l2capture *capture, unsigned int value) {//TODO auto-generated function stubif (!capture || Value > 10000) return ret_error_fail;struct V4l2_control control;control.id = V4l2_cid_brightness;control.value = 255 if (Ret_error_fail = = Xioctl (CAPTURE-&GT;FD, Vidioc_s_ctrl, &control)) {return ret_error_fail;} Capture->brightness = Control.value;return Ret_error_ok;} int v4l2camera::startdevice (int fd) {//TODO auto-generated function stubif (FD < 0) return ret_error_fail;int RET = ret_e rror_ok;for (unsigned int i = 0; i < m_nbuffers; ++i) {struct V4l2_buffer buf; Memst_value (BUF); buf.type = V4l2_buf_type_video_capture;buf.memory = V4l2_memory_mmap;buf.index = I;if ( Ret_error_fail = = Xioctl (FD, VIDIOC_QBUF, &buf)) {ret = Ret_error_capture_vidioc;break;}} Enum V4l2_buf_type type = v4l2_buf_type_video_capture;if (Ret_error_fail = = Xioctl (FD, Vidioc_streamon, &type)) RET = Ret_error_capture_vidioc;return ret;} int v4l2camera::stopdevice (int fd) {//TODO auto-generated function stubenum v4l2_buf_type type = V4l2_buf_type_video_ Capture;if (Ret_error_fail = = Xioctl (FD, Vidioc_streamoff, &type)) {return ret_error_fail;} return 0;} int v4l2camera::msleep (int fd, unsigned int msec) {fd_set FDS; Fd_zero (&fds); Fd_set (FD, &fds), struct timeval tv;tv.tv_sec = msec;tv.tv_usec = 0;return Select (FD + 1, &fds, NULL, NULL, &AMP;TV);} int V4l2camera::getframe (v4l2capture *capture) {//TODO auto-generated function stubif (!capture) return ret_error_fail; int fd = capture->fd;if (Ret_error_fail = = Msleep (CAPTURE-&GT;FD, M_stime)) return ret_error_fail;struct V4l2_buffer Buf Memst_value (BUF); buf.type = V4l2_buf_type_video_capture;buf.memory = v4l2_memory_mmap;buf.reserved = 0;//Skip the First CONFIG_CAMERA_UVC_INVAL_FRAMECNT video frames//because they is possibly invalidif (musbcameraivalidframecnt< CONFIG_CAMERA_UVC_INVAL_FRAMECNT) {musbcameraivalidframecnt++;if (Xioctl (FD, Vidioc_dqbuf, &buf) >= 0) {Xioctl (FD, VIDIOC_QBUF, &buf);} return RET_ERROR_OK;} if (Ret_error_fail = = Xioctl (FD, Vidioc_dqbuf, &buf) | | buf.index >= m_nbuffers) {return ret_error_fail;} memcpy (Capture->v4l2info.buffer, M_buffers[buf.index].start, buf.bytesused); if (Ret_error_fail = = Xioctl (FD, Vidioc_qbuf, &buf)) return Ret_error_fail;return Ret_error_ok;}} End namesPace 

  

Implementing video Reading under Linux

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.