1. Init_videoin function
int Init_videoin (struct Vdin *vd, char *device, int width, int height, int fps, int format, int grabmethod)
{
Various parameters to determine (whether the device node is empty, the resolution is 0, if not meet the requirements, direct return)
if (VD = = NULL | | device = = NULL)
return-1;
if (width = = 0 | | height = = 0)
return-1;
if (Grabmethod < 0 | | Grabmethod > 1)
Grabmethod = 1;//mmap by default;
/* Re-set each member of the Vdin struct */
Vd->videodevice = NULL;
Vd->status = NULL;
Vd->pictname = NULL;
Vd->videodevice = (char *) calloc (1, * sizeof (char));
Vd->status = (char *) calloc (1, + sizeof (char));
Vd->pictname = (char *) calloc (1, * sizeof (char));
snprintf (Vd->videodevice, +, "%s", device);
Vd->toggleavi = 0;
vd->getpict = 0;
Vd->signalquit = 1;
Vd->width = width;
Vd->height = height;
Vd->fps = fps;
Vd->formatin = format;
Vd->grabmethod = Grabmethod;
Call Init_v4l2 This function
if (INIT_V4L2 (VD) < 0)
{
fprintf (stderr, "Init V4L2 failed!! Exit fatal \ n ");
goto error;;
}
/* Alloc A temp buffer to reconstruct the PICT */
/* Allocate a temporary buffer for receiving camera data * * Different output formats have different allocation methods
Vd->framesizein = (Vd->width * vd->height << 1);
Switch (vd->formatin)
{
Case V4L2_PIX_FMT_MJPEG:
Vd->tmpbuffer = (unsigned char *) calloc (1, (size_t) Vd->framesizein);
if (!vd->tmpbuffer)
Goto error;
Vd->framebuffer =
(unsigned char *) calloc (1, (size_t) vd->width * (Vd->height + 8) * 2);
Break
Case V4L2_PIX_FMT_YUYV:
Vd->framebuffer =
(unsigned char *) calloc (1, (size_t) Vd->framesizein);
Break
Default
fprintf (stderr, "should never arrive exit fatal!! \ n ");
Goto error;
Break
}
Allocation cache is allocated successfully
if (!vd->framebuffer)
Goto error;
Successful return 0
return 0;
Error
Free (vd->videodevice);
Free (vd->status);
Free (vd->pictname);
Close (VD->FD);
return-1;
2. init_v4l2 function
static int init_v4l2 (struct Vdin *vd)
{
int i;
int ret = 0;
/* Turn on the camera's device node (/DEV/VIDE0) */specifically which device node is determined by the parameters we passed in
if ((vd->fd = open (Vd->videodevice, o_rdwr)) = = =-1)
{
Perror ("ERROR opening v4l interface");
return-1;
}
The next operation is to initialize the camera with a series of IOCTL functions provided by V4L2
/* See if the device you are opening is a video capture device */
memset (&vd->cap, 0, sizeof (struct v4l2_capability));
RET = IOCTL (VD->FD,VIDIOC_QUERYCAP, &VD->CAP);
if (Ret < 0)
{
fprintf (stderr, "Error opening device%s:unable to query device.\n", Vd->videodevice);
Goto fatal;
}
/* Determine if it is a video capture device */
if ((Vd->cap.capabilities & v4l2_cap_video_capture) = = 0)
{
fprintf (stderr, "Error opening device%s:video capture not supported.\n",
Vd->videodevice);
Goto fatal;;
}
/* Determine if the data transfer method is supported */
if (Vd->grabmethod)
{
if (! ( Vd->cap.capabilities & v4l2_cap_streaming))//stream transmission
{
fprintf (stderr, "%s does not support streaming i/o\n", vd->videodevice);
Goto fatal;
}
}
Else
{
if (! ( Vd->cap.capabilities & V4l2_cap_readwrite))//read/write mode transmission
{
fprintf (stderr, "%s does not support read i/o\n", Vd->videodevice);
Goto fatal;
}
}
/*
* Set format in
*/
/*
Set the camera's output format (resolution, output format (MJPEG/YUV))
*/
memset (&vd->fmt, 0, sizeof (struct v4l2_format));
Vd->fmt.type = v4l2_buf_type_video_capture;
Vd->fmt.fmt.pix.width = vd->width;
Vd->fmt.fmt.pix.height = vd->height;
Vd->fmt.fmt.pix.pixelformat = vd->formatin;
Vd->fmt.fmt.pix.field = V4l2_field_any;
RET = IOCTL (VD->FD, VIDIOC_S_FMT, &vd->fmt);
if (Ret < 0)
{
Perror ("Unable to set format");
Goto fatal;
}
if ((vd->fmt.fmt.pix.width! = vd->width) | |
(Vd->fmt.fmt.pix.height! = vd->height)) {
fprintf (stderr, "format asked unavailable get width%d height%d \ n", Vd->fmt.fmt.pix.width, Vd->fmt.fmt.pix.height );
Vd->width = vd->fmt.fmt.pix.width;
Vd->height = vd->fmt.fmt.pix.height;
/*
* Look the format was not part of the deal???
*/
Vd->formatin = vd->fmt.fmt.pix.pixelformat;
}
/*
* Set framerate
*/
/*
Setting camera parameters, such as the output frame rate
*/
struct V4l2_streamparm *setfps;
Setfps = (struct V4l2_streamparm *) calloc (1, sizeof (struct v4l2_streamparm));
memset (setfps, 0, sizeof (struct v4l2_streamparm));
Setfps->type = v4l2_buf_type_video_capture;
Setfps->parm.capture.timeperframe.numerator = 1;
Setfps->parm.capture.timeperframe.denominator = vd->fps;
RET = IOCTL (VD->FD, Vidioc_s_parm, Setfps);
/*
* Request Buffers
*/
/*
Request Cache
*/
memset (&VD->RB, 0, sizeof (struct v4l2_requestbuffers));
Vd->rb.count = Nb_buffer;
Vd->rb.type = v4l2_buf_type_video_capture;
Vd->rb.memory = V4l2_memory_mmap;
RET = IOCTL (VD->FD, Vidioc_reqbufs, &VD->RB);
if (Ret < 0)
{
Perror ("Unable to query buffer");
Goto fatal;
}
/*
* Map the Buffers
*/
/* Map the cache of the above request to user space */
for (i = 0; i < Nb_buffer; i++)
{
/* Get information about the video buffers in kernel space */
memset (&vd->buf, 0, sizeof (struct v4l2_buffer));
Vd->buf.index = i;
Vd->buf.type = v4l2_buf_type_video_capture;
Vd->buf.memory = V4l2_memory_mmap;
RET = IOCTL (VD->FD, Vidioc_querybuf, &vd->buf);
if (Ret < 0)
{
Perror ("Unable to query buffer");
Goto fatal;
}
if (Debug)
fprintf (stderr, "Length:%u offset:%u\n", Vd->buf.length, Vd->buf.m.offset);
/* DO mapping operations */
Vd->mem[i] = mmap (0/* Start anywhere */,
Vd->buf.length, Prot_read, map_shared, VD->FD,
Vd->buf.m.offset);
if (vd->mem[i] = = map_failed) {
Perror ("Unable to map buffer");
Goto fatal;
}
if (Debug)
fprintf (stderr, "Buffer mapped at address%p.\n", vd->mem[i]);
}
/*
* Queue the buffers.
*/
/*
Put an empty video buffer into the video buffer queue
*/
for (i = 0; i < Nb_buffer; ++i)
{
memset (&vd->buf, 0, sizeof (struct v4l2_buffer));
Vd->buf.index = i;
Vd->buf.type = v4l2_buf_type_video_capture;
Vd->buf.memory = V4l2_memory_mmap;
RET = IOCTL (VD->FD, Vidioc_qbuf, &vd->buf);
if (Ret < 0) {
Perror ("Unable to queue buffer");
Goto fatal;;
}
}
return 0;
Fatal
return-1;
}
3. Uvcgrab function
int Uvcgrab (struct Vdin *vd)
{
#define HEADERFRAME1 0xaf
int ret;
if (!vd->isstreaming)
if (video_enable (VD))//Enable video capture device, through the IOCTL hair Vidioc_streamon to achieve
Goto err;
/* Remove a video buffer that already has a frame of data from the video buffer queue */
memset (&vd->buf, 0, sizeof (struct v4l2_buffer));
Vd->buf.type = v4l2_buf_type_video_capture;
Vd->buf.memory = V4l2_memory_mmap;
RET = IOCTL (VD->FD, Vidioc_dqbuf, &vd->buf);
if (Ret < 0)
{
Perror ("Unable to dequeue buffer");
Goto err;
}
Switch (vd->formatin)
{
Case V4L2_PIX_FMT_MJPEG:
if (vd->buf.bytesused <= HEADERFRAME1)//based on the size of the video data, determine if the frame data is valid
{/* Prevent crash
* On empty image */
fprintf (stderr, "ignoring empty buffer ... \ n");
return 0;
}
/* memcpy (Vd->tmpbuffer, Vd->mem[vd->buf.index], vd->buf.bytesused);
memcpy (Vd->tmpbuffer, Vd->mem[vd->buf.index], HEADERFRAME1);
memcpy (Vd->tmpbuffer + HEADERFRAME1, dht_data, sizeof (Dht_data));
memcpy (vd->tmpbuffer + HEADERFRAME1 + sizeof (dht_data), Vd->mem[vd->buf.index] + HEADERFRAME1, (vd-> BUF.BYTESUSED-HEADERFRAME1));
*/
Copy video data to Vd->tmpbuffer
memcpy (Vd->tmpbuffer, Vd->mem[vd->buf.index], vd->buf.bytesused);
if (Debug)
fprintf (stderr, "bytes in used%d \ n", vd->buf.bytesused); If the Debug function is enabled, the debug information will be printed out
Break
Case V4L2_PIX_FMT_YUYV:
/* Copy a frame of video data to Vd->framebuffer */
if (vd->buf.bytesused > Vd->framesizein)
memcpy (Vd->framebuffer, Vd->mem[vd->buf.index], (size_t) Vd->framesizein);
Else
memcpy (Vd->framebuffer, Vd->mem[vd->buf.index], (size_t) vd->buf.bytesused);
Break
Default
Goto err;
Break
}
/* Put an empty video buffer into the video buffer queue */
RET = IOCTL (VD->FD, Vidioc_qbuf, &vd->buf);
if (Ret < 0)
{
Perror ("Unable to requeue buffer");
Goto err;
}
return 0;
Err:
Vd->signalquit = 0;
return-1;
}
4.video_enable function
static int video_enable (struct Vdin *vd)
{
int type = V4l2_buf_type_video_capture;
int ret;
RET = IOCTL (VD->FD, Vidioc_streamon, &type);
if (Ret < 0)
{
Perror ("Unable to start capture");
return ret;
}
vd->isstreaming = 1;
return 0;
}
5. Compress_yuyv_to_jpeg function
int compress_yuyv_to_jpeg (struct Vdin *vd, unsigned char *buffer, int size, int quality)
{
/*
Convert YUV to JPEG
Yuv->rgb->jpeg (using Libjpeg)
*/
struct Jpeg_compress_struct cinfo;
struct Jpeg_error_mgr jerr;
Jsamprow Row_pointer[1];
unsigned char *line_buffer, *yuyv;
int z;
static int written;
Line_buffer = Calloc (Vd->width * 3, 1);
YUYV = vd->framebuffer;
Cinfo.err = Jpeg_std_error (&jerr);
Jpeg_create_compress (&cinfo);
/* Jpeg_stdio_dest (&cinfo, file); */
Dest_buffer (&cinfo, buffer, size, &written);
Cinfo.image_width = vd->width;
Cinfo.image_height = vd->height;
Cinfo.input_components = 3;
Cinfo.in_color_space = Jcs_rgb;
Jpeg_set_defaults (&cinfo);
Jpeg_set_quality (&cinfo, quality, TRUE);
Jpeg_start_compress (&cinfo, TRUE);
z = 0;
while (Cinfo.next_scanline < vd->height) {
int x;
unsigned char *ptr = Line_buffer;
for (x = 0, x < vd->width; x + +)
{
/* First put YUV->RGB */
int R, G, B;
int y, u, v;
if (!z)
y = yuyv[0] << 8;
Else
y = yuyv[2] << 8;
U = yuyv[1]-128;
v = yuyv[3]-128;
R = (y + (359 * v)) >> 8;
g = (Y-(x * u)-(183 * v)) >> 8;
b = (y + (454 * u)) >> 8;
* (ptr++) = (R > 255)? 255: ((R < 0)? 0:r);
* (ptr++) = (g > 255)? 255: ((g < 0)? 0:g);
* (ptr++) = (b > 255)? 255: ((b < 0) 0:b);
if (z++) {
z = 0;
Yuyv + = 4;
}
}
Row_pointer[0] = Line_buffer;
Jpeg_write_scanlines (&cinfo, Row_pointer, 1);
}
Jpeg_finish_compress (&cinfo);
Jpeg_destroy_compress (&cinfo);
Free (line_buffer);
return (written);
}