Mjpg-streamer Learning Note 6----input channels-mainly related to functions

Source: Internet
Author: User
Tags goto int size

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-&GT;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-&GT;FD,VIDIOC_QUERYCAP, &AMP;VD-&GT;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-&GT;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-&GT;FD, Vidioc_s_parm, Setfps);


/*
* Request Buffers
*/
/*
Request Cache
*/
memset (&AMP;VD-&GT;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-&GT;FD, Vidioc_reqbufs, &AMP;VD-&GT;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-&GT;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-&GT;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-&GT;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-&GT;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-&GT;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-&GT;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);
}

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.