#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>
#define CAMERA_DEVICE "/dev/video1"
#define CAPTURE_FILE "frame_yuyv_new.jpg"
#define CAPTURE_RGB_FILE "frame_rgb_new.bmp"
#define CAPTURE_show_FILE "a.bmp"
#define VIDEO_WIDTH 640
#define VIDEO_HEIGHT 480
#define VIDEO_FORMAT V4L2_PIX_FMT_YUYV
#define BUFFER_COUNT 4
/*#define VIDEO_WIDTH 1280
#define VIDEO_HEIGHT 1024
#define VIDEO_FORMAT V4L2_PIX_FMT_YUYV
#define BUFFER_COUNT */
typedef struct VideoBuffer {
void *start;
size_t length;
} VideoBuffer;
#pragma pack(1)
typedef struct BITMAPFILEHEADER
{
unsigned short bfType;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
} BITMAPFILEHEADER;
#pragma pack()
typedef struct BITMAPINFOHEADER
{
unsigned long biSize;
unsigned long biWidth;
unsigned long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
unsigned long biXPelsPerMeter;
unsigned long biYPelsPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
} BITMAPINFOHEADER;
VideoBuffer framebuf[BUFFER_COUNT];
int fd;
struct v4l2_capability cap;
struct v4l2_fmtdesc fmtdesc;
struct v4l2_format fmt;
struct v4l2_requestbuffers reqbuf;
struct v4l2_buffer buf;
unsigned char *starter;
unsigned char *newBuf;
struct BITMAPFILEHEADER bfh;
struct BITMAPINFOHEADER bih;
void create_bmp_header()
{
bfh.bfType = (unsigned short)0x4D42;
bfh.bfSize = (unsigned long)(14 + 40 + VIDEO_WIDTH * VIDEO_HEIGHT*3);
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = (unsigned long)(14 + 40);
bih.biBitCount = 24;
bih.biWidth = VIDEO_WIDTH;
bih.biHeight = VIDEO_HEIGHT;
bih.biSizeImage = VIDEO_WIDTH * VIDEO_HEIGHT * 3;
bih.biClrImportant = 0;
bih.biClrUsed = 0;
bih.biCompression = 0;
bih.biPlanes = 1;
bih.biSize = 40;//sizeof(bih);
bih.biXPelsPerMeter = 0x00000ec4;
bih.biYPelsPerMeter = 0x00000ec4;
}
int open_device()
{
int fd;
fd = open(CAMERA_DEVICE, O_RDWR, 0);//
if (fd < 0) {
printf("Open %s failed\n", CAMERA_DEVICE);
return -1;
}
return fd;
}
void get_capability()
{
int ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
if (ret < 0) {
printf("VIDIOC_QUERYCAP failed (%d)\n", ret);
return;
}
// Print capability infomations
printf("------------VIDIOC_QUERYCAP-----------\n");
printf("Capability Informations:\n");
printf(" driver: %s\n", cap.driver);
printf(" card: %s\n", cap.card);
printf(" bus_info: %s\n", cap.bus_info);
printf(" version: %08X\n", cap.version);
printf(" capabilities: %08X\n\n", cap.capabilities);
return;
}
void get_format()
{
int ret;
fmtdesc.index=0;
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret=ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc);
while (ret != 0)
{
fmtdesc.index++;
ret=ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc);
}
printf("--------VIDIOC_ENUM_FMT---------\n");
printf("get the format what the device support\n{ pixelformat = ''%c%c%c%c'', description = ''%s'' }\n",fmtdesc.pixelformat & 0xFF, (fmtdesc.pixelformat >> 8) & 0xFF, (fmtdesc.pixelformat >> 16) & 0xFF,(fmtdesc.pixelformat >> 24) & 0xFF, fmtdesc.description);
return;
}
int set_format()
{
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = VIDEO_WIDTH;
fmt.fmt.pix.height = VIDEO_HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
//fmt.fmt.pix.pixelformat = fmtdesc.pixelformat;//V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
int ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
if (ret < 0) {
printf("VIDIOC_S_FMT failed (%d)\n", ret);
return;
}
printf("------------VIDIOC_S_FMT---------------\n");
printf("Stream Format Informations:\n");
printf(" type: %d\n", fmt.type);
printf(" width: %d\n", fmt.fmt.pix.width);
printf(" height: %d\n", fmt.fmt.pix.height);
char fmtstr[8];
memset(fmtstr, 0, 8);
memcpy(fmtstr, &fmt.fmt.pix.pixelformat, 4);
printf(" pixelformat: %s\n", fmtstr);
printf(" field: %d\n", fmt.fmt.pix.field);
printf(" bytesperline: %d\n", fmt.fmt.pix.bytesperline);
printf(" sizeimage: %d\n", fmt.fmt.pix.sizeimage);
printf(" colorspace: %d\n", fmt.fmt.pix.colorspace);
printf(" priv: %d\n", fmt.fmt.pix.priv);
printf(" raw_date: %s\n", fmt.fmt.raw_data);
return;
}
void request_buf()
{
reqbuf.count = BUFFER_COUNT;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
int ret = ioctl(fd , VIDIOC_REQBUFS, &reqbuf);
if(ret < 0) {
printf("VIDIOC_REQBUFS failed (%d)\n", ret);
return;
}
printf("the buffer has been assigned successfully!\n");
return;
}
void query_map_qbuf()
{
int i,ret;
for (i = 0; i < reqbuf.count; i++)
{
buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd , VIDIOC_QUERYBUF, &buf);//buf取得内存缓冲区的信息
if(ret < 0) {
printf("VIDIOC_QUERYBUF (%d) failed (%d)\n", i, ret);
return;
}
// mmap buffer
framebuf[i].length = buf.length;//framebuf是程序最前面定义的一个结构体类型的数据
framebuf[i].start = (char *) mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
if (framebuf[i].start == MAP_FAILED) {
printf("mmap (%d) failed: %s\n", i, strerror(errno));
return;
}
// Queen buffer
ret = ioctl(fd , VIDIOC_QBUF, &buf);
if (ret < 0) {
printf("VIDIOC_QBUF (%d) failed (%d)\n", i, ret);
return;
}
printf("Frame buffer %d: address=0x%x, length=%d\n", i, (unsigned int)framebuf[i].start, framebuf[i].length);
}
return;
}
void yuyv2rgb()
{
unsigned char YUYV[4],RGB[6];
int j,k,i;
unsigned int location=0;
j=0;
for(i=0;i < framebuf[buf.index].length;i+=4)
{
YUYV[0]=starter[i];//Y0
YUYV[1]=starter[i+1];//U
YUYV[2]=starter[i+2];//Y1
YUYV[3]=starter[i+3];//V
if(YUYV[0]<1)
{
RGB[0]=0;
RGB[1]=0;
RGB[2]=0;
}
else
{
RGB[0]=YUYV[0]+1.772*(YUYV[1]-128);//b
RGB[1]=YUYV[0]-0.34413*(YUYV[1]-128)-0.71414*(YUYV[3]-128);//g
RGB[2]=YUYV[0]+1.402*(YUYV[3]-128);//r */
/*RGB[0]=YUYV[0]+2.03*(YUYV[1]-128);//b
RGB[1]=YUYV[0]-0.39*(YUYV[1]-128)-0.58*(YUYV[3]-128);//g
RGB[2]=YUYV[0]+1.14*(YUYV[3]-128);//r */
}
if(YUYV[2]<0)
{
RGB[3]=0;
RGB[4]=0;
RGB[5]=0;
}
else