Convert the yuyv format collected by the USB camera in Linux to JPEG format

Source: Internet
Author: User

Because some cameras currently collect yuyv images and cannot convert them into JPEG image formats by themselves, it is quite troublesome for us to watch .. Therefore, the source code of MJPEG-streamer is referenced.

The conversion function is obtained from this function. You can convert the format of yuyv to JPEG through your own combination, so that we can implement remote monitoring through the network. The source code is as follows:

// The code is complicated and not organized ..

# Include <stdio. h>

# Include <stdlib. h>

# Include <string. h>

# Include <assert. h>

# Include <getopt. h>

# Include <fcntl. h>

# Include <unistd. h>

# Include <errno. h>

# Include <malloc. h>

# Include <sys/STAT. h>

# Include <sys/types. h>

# Include <sys/time. h>

# Include <sys/Mman. h>

# Include <sys/IOCTL. h>

# Include <ASM/types. h>

# Include <Linux/videodev2.h>

# Include <cmdlib. h>

 

# Define output_buf_size 4096

# Define clear (x) memset (& (x), 0, sizeof (x ))

# Define width 320

# Define height 240

 

Struct buffer {

Void * start;

Size_t length;

};

 

Typedef struct {

Struct cmd_destination_mgr pub;

 

Joctet * buffer;

 

Unsigned char * outbuffer;

Int outbuffer_size;

Unsigned char * outbuffer_cursor;

Int * written;

 

} Mjpg_destination_mgr;

 

Typedef mjpg_destination_mgr * mjpg_dest_ptr;

 

Static char * dev_name = "/dev/video0 ";

Static int FD =-1;

Struct buffer * buffers = NULL;

Static unsigned int n_buffers = 0;

File * file_fd;

Static unsigned long file_length;

Static unsigned char * file_name;

 

Methoddef (void) init_destination (j_compress_ptr Cinfo ){

Mjpg_dest_ptr DEST = (mjpg_dest_ptr) Cinfo-> DEST;

DeST-> buffer = (joctet *) (* Cinfo-> mem-> alloc_small) (j_common_ptr) Cinfo, jpool_image, output_buf_size * sizeof (joctet ));

* (DEST-> written) = 0;

DeST-> pub. next_output_byte = DEST-> buffer;

DeST-> pub. free_in_buffer = output_buf_size;

}

 

Methoddef (Boolean) empty_output_buffer (j_compress_ptr Cinfo ){

Mjpg_dest_ptr DEST = (mjpg_dest_ptr) Cinfo-> DEST;

Memcpy (DEST-> outbuffer_cursor, DEST-> buffer, output_buf_size );

DeST-> outbuffer_cursor + = output_buf_size;

* (DEST-> written) + = output_buf_size;

DeST-> pub. next_output_byte = DEST-> buffer;

DeST-> pub. free_in_buffer = output_buf_size;

 

Return true;

}

 

Methoddef (void) term_destination (j_compress_ptr Cinfo ){

Mjpg_dest_ptr DEST = (mjpg_dest_ptr) Cinfo-> DEST;

Size_t datacount = output_buf_size-Dest-> pub. free_in_buffer;

/* Write any data remaining in the buffer */

Memcpy (DEST-> outbuffer_cursor, DEST-> buffer, datacount );

DeST-> outbuffer_cursor + = datacount;

* (DEST-> written) + = datacount;

}

 

Void dest_buffer (j_compress_ptr Cinfo, unsigned char * buffer, int size, int * written ){

Mjpg_dest_ptr DEST;

If (Cinfo-> DEST = NULL ){

Cinfo-> DEST = (struct cmd_destination_mgr *) (* Cinfo-> mem-> alloc_small) (j_common_ptr) Cinfo, jpool_permanent, sizeof (mjpg_destination_mgr ));

}

 

DeST = (mjpg_dest_ptr) Cinfo-> DEST;

DeST-> pub. init_destination = init_destination;

DeST-> pub. empty_output_buffer = empty_output_buffer;

DeST-> pub. term_destination = term_destination;

DeST-> outbuffer = buffer;

DeST-> outbuffer_size = size;

DeST-> outbuffer_cursor = buffer;

DeST-> written = written;

}

 

// Convert the yuyv format collected by the camera to JPEG format

Int compress_yuyv_to_jpeg (unsigned char * Buf, unsigned char * buffer, int size, int quality ){

Struct performance_compress_struct Cinfo;

Struct performance_error_mgr Jerr;

Jsamprow row_pointer [1];

Unsigned char * line_buffer, * yuyv;

Int Z;

Static int written;

// Int COUNT = 0;

// Printf ("% s \ n", Buf );

Line_buffer = calloc (width * 3, 1 );

Yuyv = Buf; // assign the image data in yuyv format to the yuyv pointer.

Printf ("compress start... \ n ");

Cinfo. Err = maid (& Jerr );

Pai_create_compress (& Cinfo );

/* Pai_stdio_dest (& Cinfo, file );*/

Dest_buffer (& Cinfo, buffer, size, & written );

 

Cinfo. image_width = width;

Cinfo. image_height = height;

Cinfo. input_components = 3;

Cinfo. in_color_space = jcs_rgb;

 

Pai_set_defaults (& Cinfo );

Performance_set_quality (& Cinfo, quality, true );

Performance_start_compress (& Cinfo, true );

 

Z = 0;

While (Cinfo. next_scanline

Int X;

Unsigned char * PTR = line_buffer;

 

For (x = 0; x <width; X ++ ){

Int R, G, B;

Int y, U, V;

 

If (! Z)

Y = yuyv [0] <8;

Else

Y = yuyv [2] <8;

U = yuyv [1]-128;

V = Yu YV [3]-128;

 

R = (Y + (359 * V)> 8;

G = (Y-(88 * u)-(183 x 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;

Pai_write_scanlines (& Cinfo, row_pointer, 1 );

}

Pai_finish_compress (& Cinfo );

Pai_destroy_compress (& Cinfo );

 

Free (line_buffer );

Return (written );

}

 

// Read the content of a frame

Static int read_frame (void)

{

Struct v4l2_buffer Buf;

Int ret;

Unsigned int I;

Clear (BUF );

Buf. type = v4l2_buf_type_video_capture;

Buf. Memory = v4l2_memory_mmap;

Int FF = IOCTL (FD, vidioc_dqbuf, & BUF); // buffer of frames collected from columns

If (FF <0)

Printf ("failture \ n ");

Unsigned char SRC [Buf. Length + 1];

Unsigned char Dest [Buf. Length + 1];

Assert (BUF. index <n_buffers );

Printf ("Buf. Index DQ is % d, \ n", Buf. Index );

 

Memcpy (SRC, buffers [Buf. Index]. Start, Buf. Length );

Ret = compress_yuyv_to_jpeg (SRC, DEST, (width * height), 80); // Data Conversion

Fwrite (DEST, RET, 1, file_fd); // write data after conversion

FF = IOCTL (FD, vidioc_qbuf, & BUF); // re-import the column

If (FF <0)

Printf ("failture vidioc_qbuf \ n ");

Return 1;

}

 

Int get_picture ()

{

Struct v4l2_capability cap;

Struct v4l2_format FMT;

Unsigned int I;

Enum v4l2_buf_type;

 

File_fd = fopen ("test-mmap.jpg", "W ");

FD = open (dev_name, o_rdwr | o_nonblock, 0 );

Int FF = IOCTL (FD, vidioc_querycap, & Cap); // obtain camera parameters

 

If (FF <0)

Printf ("failture vidioc_querycap \ n ");

 

Struct v4l2_fmtdesc fmt1;

Int ret;

 

Memset (& fmt1, 0, sizeof (fmt1 ));

Fmt1.index = 0;

Fmt1.type = v4l2_buf_type_video_capture;

While (ret = IOCTL (FD, vidioc_enum_fmt, & fmt1) = 0) // view the formats supported by the camera

{

Fmt1.index ++;

Printf ("{pixelformat = '% C % C', description =' % s'} \ n ",

Fmt1.pixelformat & 0xff, (fmt1.pixelformat> 8) & 0xff,

(Fmt1.pixelformat> 16) & 0xff, (fmt1.pixelformat> 24) & 0xff,

Fmt1.description );

}

Clear (FMT );

FMT. type = v4l2_buf_type_video_capture;

FMT. FMT. pix. width = 640;

FMT. FMT. pix. Height = 480;

FMT. FMT. pix. pixelformat = v4l2_pix_fmt_yuyv;

FMT. FMT. pix. Field = v4l2_field_interlaced;

 

FF = IOCTL (FD, vidioc_s_fmt, & FMT); // sets the image format

If (FF <0)

Printf ("failture vidioc_s_fmt \ n ");

 

File_length = FMT. FMT. pix. bytesperline * FMT. FMT. pix. height; // calculate the image size.

Struct v4l2_requestbuffers req;

Clear (req );

Req. Count = 1;

Req. type = v4l2_buf_type_video_capture;

Req. Memory = v4l2_memory_mmap;

 

IOCTL (FD, vidioc_reqbufs, & req); // Request Buffer. Count indicates the number of requests.

If (FF <0)

Printf ("failture vidioc_reqbufs \ n ");

If (req. Count <1)

Printf ("insufficient buffer memory \ n ");

Buffers = calloc (req. Count, sizeof (* buffers); // create the corresponding space in the memory

 

 

For (n_buffers = 0; n_buffers <Req. Count; ++ n_buffers)

{

Struct v4l2_buffer Buf;

Clear (BUF );

Buf. type = v4l2_buf_type_video_capture;

Buf. Memory = v4l2_memory_mmap;

Buf. Index = n_buffers;

If (-1 = IOCTL (FD, vidioc_querybuf, & BUF) // map the user space

Printf ("vidioc_querybuf error \ n ");

Buffers [n_buffers]. Length = Buf. length;

Buffers [n_buffers]. Start = MMAP (null, Buf. length, prot_read | prot_write, map_shared, FD, Buf. M. offset); // create a ing through MMAP

If (map_failed = buffers [n_buffers]. Start)

Printf ("MMAP failed \ n ");

}

 

For (I = 0; I <n_buffers; ++ I)

{

Struct v4l2_buffer Buf;

Clear (BUF );

Buf. type = v4l2_buf_type_video_capture;

Buf. Memory = v4l2_memory_mmap;

Buf. Index = I;

If (-1 = IOCTL (FD, vidioc_qbuf, & BUF) // The requested buffer enters the queue

Printf ("vidioc_qbuf failed \ n ");

}

Type = v4l2_buf_type_video_capture;

If (-1 = IOCTL (FD, vidioc_streamon, & type) // start capturing image data

Printf ("vidioc_streamon failed \ n ");

 

For (;) // This section involves asynchronous Io

{

Fd_set FDS;

Struct timeval TV;

Int R;

Fd_zero (& FDs); // clears the specified file descriptor set

Fd_set (FD, & FDs); // Add a new file descriptor to the file descriptor set.

/* Timeout .*/

TV. TV _sec = 2;

TV. TV _usec = 0;

R = select (FD + 1, & FDS, null, null, & TV); // determines whether the camera is readable (that is, whether the camera is ready), and TV is timed

If (-1 = r)

{

If (eintr = errno)

Continue;

Printf ("select err \ n ");

}

If (0 = r)

{

Fprintf (stderr, "select timeout \ n ");

Exit (exit_failure );

}

 

If (read_frame () // if it is readable, run the read_frame function.
Break;
}
Unmap:
For (I = 0; I <n_buffers; ++ I)
If (-1 = munmap (buffers [I]. Start, buffers [I]. Length ))
Printf ("munmap error ");
Type = v4l2_buf_type_video_capture;

If (-1 = IOCTL (FD, vidioc_streamoff, & type ))
Printf ("vidioc_streamoff ");
Close (FD );
Fclose (file_fd );
Exit (exit_success );
Return 0;
}

 

 

 

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.