#include "./v4l2_driver.h"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include "stdlib.h"
u_int8_t map_stat = 0;
u_int8_t req_stat = 0;
u_int8_t que_stat = 0;
// unsigned char *data[COUNT]={0};
unsigned char recbuf[IMG_WIDTH*IMG_HEIGHT*3] = {0};
unsigned int ret_get[SCR_WIDTH*SCR_HEIGHT] = {0};
unsigned short recbuf_yuyv[IMG_WIDTH*IMG_HEIGHT*2] = {0};
FILE *ptr;
unsigned char RGB888[IMG_WIDTH*IMG_HEIGHT*3] = {0};
bmphead bmph;
bmpbody bmpb;
/* functions definations */
u_int8_t Cap_Init(char* dev,int *cap)
{
/* 第一步,打开摄像头 */
int ret;
int i;
//FILE *ptr;
*cap = open(dev,O_RDWR);//以读写权限打开设备文件
if(-1 == *cap)
{
printf("cap open failed!\r\n");
return false;
}
/* 第二部,设置摄像头图片帧格式 */
cap_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//操作类型为获取图片
cap_format.fmt.pix.width = IMG_WIDTH;//输出图片宽度
cap_format.fmt.pix.height = IMG_HEIGHT;//输出图片高度
cap_format.fmt.pix.pixelformat = IMG_FMT;//图片编码格式
cap_format.fmt.pix.field = V4L2_FIELD_ALTERNATE;
ret = ioctl(*cap,VIDIOC_S_FMT,&cap_format);//将设置配置到摄像头
printf("return2:%d\r\n",ret);
printf("pixelformat=%c,%c,%c,%c\r\n",cap_format.fmt.pix.pixelformat,cap_format.fmt.pix.pixelformat>>8,cap_format.fmt.pix.pixelformat>>16,cap_format.fmt.pix.pixelformat>>24);
fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmtdesc.index=0;
while(ioctl(*cap,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)
{
printf("\t:%d.%s\n",fmtdesc.index+1,fmtdesc.description);
fmtdesc.index++;
}
/*
*VIDIOC->video io control
* S -> set
* FMT -> format
* 视频格式设置
*/
if(-1 == ret)
{
// printf("设置摄像头输出图片帧格式出错\r\n");
// close(*cap);
// return false;
}
/* 第三部,获取摄像头格式信息,检查设置是否成功 */
ret = ioctl(*cap,VIDIOC_G_FMT,&cap_format);
printf("return3:%d\r\n",ret);
/*
*VIDIOC->video io control
* G -> get
* FMT -> format
* 获取视频格式设置
*/
if(-1 == ret)
{
printf("get cap info failed!\r\n");
// close(*cap);
// return false;
}
if(cap_format.fmt.pix.width != IMG_WIDTH)
{
printf("capout width set failed!width:%d\r\n",cap_format.fmt.pix.width);
}
else
{
printf("capout width set ok!\r\n");
}
if(cap_format.fmt.pix.height != IMG_HEIGHT)
{
printf("capout height set failed!height:%d\r\n",cap_format.fmt.pix.height);
}
else
{
printf("capout height set ok!\r\n");
}
if(cap_format.fmt.pix.pixelformat != v4l2_fourcc('J', 'P', 'E', 'G'))
{
printf("capout FMT set failed!!pixelformat=%c,%c,%c,%c\r\n",cap_format.fmt.pix.pixelformat,cap_format.fmt.pix.pixelformat>>8,cap_format.fmt.pix.pixelformat>>16,cap_format.fmt.pix.pixelformat>>24);
}
else
{
printf("capout FMT set ok!pixelformat=%c,%c,%c,%c\r\n",cap_format.fmt.pix.pixelformat,cap_format.fmt.pix.pixelformat>>8,cap_format.fmt.pix.pixelformat>>16,cap_format.fmt.pix.pixelformat>>24);
}
/* 第四步,申请图像缓冲区 */
reqbuf.count = COUNT;//缓冲区个数
reqbuf.type = BUF_TYPE;//缓冲区类型
reqbuf.memory = V4L2_MEMORY_MMAP;//内存映射
ret = ioctl(*cap,VIDIOC_REQBUFS,&reqbuf);//请求缓冲区
printf("return4:%d\r\n",ret);
if(-1 == ret)
{
printf("缓冲区请求失败!\r\n");
close(*cap);
return false;
}
for(i=0;i<COUNT;i++)
{
/* 第五步,查询每个缓冲区的信息,进行内存映射 */
imgbuf[i].index = i;
imgbuf[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
imgbuf[i].memory = V4L2_MEMORY_MMAP;
ret = ioctl(*cap,VIDIOC_QUERYBUF,&imgbuf[i]);
if(-1 == ret)
{
printf("Index%d缓冲区映射失败!\r\n",i);
req_stat = -1;
}
printf("Index:%d lens:%d offset:%d\r\n",i,imgbuf[i].length,imgbuf[i].m.offset);//打印对应缓冲区的偏移量和长度
//将映射的缓冲区放到进程中来(date)
data[i] = mmap(NULL,imgbuf[i].length,PROT_READ|PROT_WRITE,MAP_SHARED,*cap,imgbuf[i].m.offset);
printf("data[i]=0x%x\r\n",data[i]);
if(MAP_FAILED == data[i])
{
printf("mmap failed!\r\n");
map_stat = -1;
break;
}
//将mmap成功的imgbuf加入图像采集队列
ret = ioctl(*cap,VIDIOC_QBUF,&imgbuf[i]);
if(-1 == ret)
{
printf("缓冲区加入图像队列失败!\r\n");
que_stat = -1;
break;
}
}
/*
*这样一来,imgbuf采集到摄像头的图片帧
*就会映射到date数组里
*我们就能通过处理date来对图像进行操作
*/
//error deal
if(-1 == req_stat)
{
}
if(-1 == map_stat)
{
close(*cap);
return false;
}
if(-1 == que_stat)
{
close(*cap);
return false;
}
return true;
}
u_int8_t capture_start(int *cap)
{
enum v4l2_buf_type on = V4L2_BUF_TYPE_VIDEO_CAPTURE;//采集开启标志位
int ret;
ret = ioctl(*cap,VIDIOC_STREAMON,&on);
if(-1 == ret)
{
printf("开启采集失败!\r\n");
close(*cap);
return false;
}
return true;
}
u_int8_t capture_stop(int *cap)
{
enum v4l2_buf_type off = V4L2_BUF_TYPE_VIDEO_CAPTURE;//采集关闭标志位
int ret;
ret = ioctl(*cap,VIDIOC_STREAMOFF,&off);
if(-1 == ret)
{
printf("停止采集失败!\r\n");
close(*cap);
return false;
}
return true;
}
u_int8_t exit_cap(int *cap)
{
int i;
for(i=0;i<COUNT;i++)
{
munmap(data[i],imgbuf[i].length);
}
close(*cap);
return true;
}
int RGB565toRGB888(unsigned short RGB565)
{
unsigned char RGB888[3]={0,0,0};
RGB888[0] = (RGB565 & 0x001F);//b
RGB888[1] = (RGB565 & 0x07E0)>>1;//g
RGB888[2] = (RGB565 & 0xF800)>>3;//r
return *RGB888;
}
void RGB565ToRGB888ToSCR(char * rgb565_1)
{
// int pix;
// int rgb_pix = 0;
// unsigned short RGB565;
// for(pix=0;pix<IMG_WIDTH*IMG_HEIGHT*2;pix+=2)
// {
// RGB565=rgb565_1[pix+1]<<8|rgb565_1[pix];
// RGB888[rgb_pix+2] = (RGB565 & RGB565_MASK_RED) >> 11;
// RGB888[rgb_pix+1] = (RGB565 & RGB565_MASK_GREEN) >> 5;
// RGB888[rgb_pix] = (RGB565 & RGB565_MASK_BLUE);
// //往高位移动填满单字节的8位
// RGB888[rgb_pix+2] <<= 3;
// RGB888[rgb_pix+1] <<= 2;
// RGB888[rgb_pix] <<= 3;
// ret_get[pix/2]=RGB888[rgb_pix+2]<<16|RGB888[rgb_pix+1]<<8|RGB888[rgb_pix];
// rgb_pix+=3;
// }
int i = 0;
int rgb_pix = 0;
int pix=0;
int k = 0;
unsigned short RGB565;
for( k = 0;k<SCR_HEIGHT;k++)
for( i = 0;i<SCR_WIDTH;i++)
{
if( (i>=IMG_WIDTH) || (k>=IMG_HEIGHT) )
ret_get[i+k*SCR_WIDTH] = 0;
else
{
RGB565=rgb565_1[pix+1]<<8|rgb565_1[pix];
pix+=2;
RGB888[rgb_pix+2] = RGB565>>8;
RGB888[rgb_pix+1] = RGB565>>3;
RGB888[rgb_pix] = RGB565<<3;
ret_get[i+k*SCR_WIDTH] = (unsigned int)(RGB888[rgb_pix+2]<<16|RGB888[rgb_pix+1]<<8|RGB888[rgb_pix]);
rgb_pix+=3;
}
}
}
u_int8_t LCD_SHOW(int *cap,int fb,unsigned int *paddr)
{
int i = 0;
int j = 0;
int k = 0;
int ret;
//FILE *ptr;
struct v4l2_buffer current_buf;
struct timeval tv;
fd_set fds;
FD_ZERO(&fds);
FD_SET(*cap, &fds);
tv.tv_sec = 0;//time out
tv.tv_usec = 50000;
ret = select(*cap+1, &fds, NULL, NULL, &tv);//判断摄像头是否准备好,tv是定时
评论0