版权声明:本文为博主原创文章,转载请注明转载地址。
使用的usb camera 是 0ac8:3420,使用网上找到的代码改
保存在图片,中间的LCD部分可以删了,我还要用就没改。
- /*
- * main.c
- *
- * Created on: Apr 25, 2016
- * Author: anzyelay
- */
- #include <unistd.h>
- #include <linux/fb.h>
- #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 "bmp.h"
- #define CAMERA_DEVICE "/dev/video0"
- #define FB_DEVICE "/dev/fb0"
- #define VIDEO_WIDTH 640
- #define VIDEO_HEIGHT 480
- #define BUFFER_COUNT 4
- typedef struct VideoBuffer {
- void *start;
- size_t length;
- } VideoBuffer;
- VideoBuffer framebuf[BUFFER_COUNT];
- //查表法,把YUV422转换为RGB32
- void process(unsigned long *rgb_buf, unsigned char *v_buf)
- {
- int r,g,b;
- int u,v;
- int y[2];
- int rv,guv,bu,i;
- unsigned int *fb_buf = (unsigned int *)rgb_buf;
- y[0]=(int)*v_buf;
- v=(int)*(v_buf+1);
- y[1]=(int)*(v_buf+2);
- u=(int)*(v_buf+3);
- rv=rvarrxyp[v];
- guv=guarrxyp[u]+gvarrxyp[v];
- bu=buarrxyp[u];
- for(i=0;i<2;i++){
- r=y[i]+rv;
- g=y[i]-guv;
- b=y[i]+bu;
- if (r>255) r=255;
- if (r<0) r=0;
- if (g>255) g=255;
- if (g<0) g=0;
- if (b>255) b=255;
- if (b<0) b=0;
- *(fb_buf+i)=(b<<16)+(g<<8)+r;
- }
- }
- int main()
- {
- int i, ret;
- // 打开摄像头设备
- int fd;
- fd = open(CAMERA_DEVICE, O_RDWR, 0);
- if (fd < 0) {
- printf("Open %s failed\n", CAMERA_DEVICE);
- return -1;
- }
- // 获取驱动信息
- struct v4l2_capability cap;
- ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
- if (ret < 0) {
- printf("VIDIOC_QUERYCAP failed (%d)\n", ret);
- goto __error1;
- }
- 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: %u.%u.%u\n", (cap.version>>16)&0XFF, (cap.version>>8)&0XFF,cap.version&0XFF);
- printf(" capabilities: %08X\n", cap.capabilities);
- // 设置视频格式
- struct v4l2_format fmt;
- memset(&fmt, 0, sizeof(fmt));
- 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.field = V4L2_FIELD_INTERLACED;
- ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
- if (ret < 0) {
- printf("VIDIOC_S_FMT failed (%d)\n", ret);
- goto __error1;
- }
- //获取视频格式(原因是设置视频格式时如果有错误,VIDIOC_S_FMT时会自动转换成合作的格式,所以再获取一次)
- ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
- if (ret < 0) {
- printf("VIDIOC_G_FMT failed (%d)\n", ret);
- goto __error1;
- }
- // Print Stream Format
- 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);
- //-----------------------------------------------
- //请求分配内存
- struct v4l2_requestbuffers reqbuf;
- reqbuf.count = BUFFER_COUNT;
- reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- reqbuf.memory = V4L2_MEMORY_MMAP;
- ret = ioctl(fd , VIDIOC_REQBUFS, &reqbuf);//在内核虚拟地址空间中申请reqbuf.count个连续的内存
- if(ret < 0) {
- printf("VIDIOC_REQBUFS failed (%d)\n", ret);
- goto __error1;
- }
- struct v4l2_buffer buf;
- for (i = 0; i < reqbuf.count; i++)
- {
- buf.index = i;
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- //根据buf.index询访内存为后面的映射做准备(本质就是设置buf.m.offset+=buf.length偏移)
- ret = ioctl(fd , VIDIOC_QUERYBUF, &buf);
- if(ret < 0) {
- printf("VIDIOC_QUERYBUF (%d) failed (%d)\n", i, ret);
- goto __error1;
- }
- //映射到用户空间
- //就是将之前内核分配的视频缓冲(VIDIOC_REQBUFS)映射到用户空间,这样用户空间就可以直接读取内核扑获的视频数据
- //buf.m.offset表示要对内核中的哪个video buffer进行映射操作
- framebuf[i].length = buf.length;
- 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));
- ret = -1;
- goto __error1;
- }
- //内存入队列
- ret = ioctl(fd , VIDIOC_QBUF, &buf);
- if (ret < 0) {
- printf("VIDIOC_QBUF (%d) failed (%d)\n", i, ret);
- goto __error2;
- }
- printf("Frame buffer %d: address=0x%x, length=%d\n", i,
- (unsigned long)framebuf[i].start,
- (unsigned int)framebuf[i].length);
- }
- //--------------------------------------
- // 启动视频流
- enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- ret = ioctl(fd, VIDIOC_STREAMON, &type);
- if (ret < 0) {
- printf("VIDIOC_STREAMON failed (%d)\n", ret);
- goto __error2;
- }
- struct fb_var_screeninfo vinfo;
- struct fb_fix_screeninfo finfo;
- int x,y;
- int fd_fb;
- long int screen_size = 0;
- unsigned long *fbp32 = NULL;
- //打开LCD设备
- fd_fb = open(FB_DEVICE, O_RDWR);
- if (fd_fb < 0)
- {
- printf("Error: cannot open framebuffer device.\n");
- goto __error2;
- }
- if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &finfo))
- {
- printf("Error reading fixed information.\n");
- goto __error3;
- }
- //获取LCD属性信息
- if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &vinfo))
- {
- printf("Error 2 reading variable information.\n");
- goto __error3;
- }
- //一屏的字节数
- screen_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
- printf("LCD: %dx%d, %dbpp, screen_size = %ld\n",
- vinfo.xres,
- vinfo.yres,
- vinfo.bits_per_pixel,
- screen_size );
- //映射framebuffer到用户空间
- fbp32 = (unsigned long *)mmap(0, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
- if (fbp32 == MAP_FAILED)
- {
- printf("Error: failed to map framebuffer device to memory.\n");
- goto __error3;
- }
- printf("start camera testing...\n");
- //开始视频显示
- // while(1)
- unsigned long *picdata = (unsigned long *)malloc(fmt.fmt.pix.height*fmt.fmt.pix.width*4);
- memset(picdata,0,fmt.fmt.pix.height*fmt.fmt.pix.width*4);
- for(i=0;i<1;i++)
- {
- memset(&buf,0,sizeof(buf));
- buf.index = 0;
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- //内存空间出队列
- ret = ioctl(fd, VIDIOC_DQBUF, &buf);
- if (ret < 0)
- {
- printf("VIDIOC_DQBUF failed (%d)\n", ret);
- break;
- }
- if(vinfo.bits_per_pixel == 32)
- {
- //yuv422 两个像素占4个字节(Y0,V,Y1,U),两个像素共用一个UV对,总字节数为W*H*2,
- //而RGB32则正好两个像素是一个LONG型对齐,以LONG为单位一次可计算两个像素点,之后framebuf自增4个字节地址指向一两个像素点
- for(y = 0; y < fmt.fmt.pix.height; y++)
- {
- for(x = 0; x < fmt.fmt.pix.width/2; x++)
- {
- //YUV422转换为RGB32
- // process(fbp32 + y*vinfo.xres + x,
- // (U8 *)framebuf[buf.index].start + (y*fmt.fmt.pix.width+x)*2);
- //由于是以long为基数自增,所以一行long数为:width(long)=width(int)/2
- process((picdata + y*fmt.fmt.pix.width/2 + x),
- (U8 *)framebuf[buf.index].start + y*fmt.fmt.pix.width*2+x*4);
- }
- }
- }
- // 内存重新入队列
- ret = ioctl(fd, VIDIOC_QBUF, &buf);
- if (ret < 0)
- {
- printf("VIDIOC_QBUF failed (%d)\n", ret);
- break;
- }
- }//while(1)
- /*save image picture captured*/
- char picname[100];
- sprintf(picname,"./niu_%d*%d.bmp",fmt.fmt.pix.width,fmt.fmt.pix.height);
- GenBmpFile((U8 *)picdata,32,fmt.fmt.pix.width,fmt.fmt.pix.height,picname);
- //释放fbp32资源
- munmap(fbp32, screen_size);
- __error3://关闭fd_fb设备
- close(fd_fb);
- __error2://释放framebuf资源
- for (i=0; i< 4; i++)
- {
- munmap(framebuf[i].start, framebuf[i].length);
- }
- __error1://关闭fd设备
- close(fd);
- return ret;
- }
- //------------save image picture captured--------///
- int GenBmpFile(U8 *pData, U8 bitCountPerPix, U32 width, U32 height, const char *filename)
- {
- FILE *fp = fopen(filename, "wb");
- if(!fp)
- {
- printf("fopen failed : %s, %d\n", __FILE__, __LINE__);
- return 0;
- }
- U32 bmppitch = ((width*bitCountPerPix + 31) >> 5) << 2;
- U32 filesize = bmppitch*height;
- BITMAPFILE bmpfile;
- bmpfile.bfHeader.bfType = 0x4D42;
- bmpfile.bfHeader.bfSize = filesize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
- bmpfile.bfHeader.bfReserved1 = 0;
- bmpfile.bfHeader.bfReserved2 = 0;
- bmpfile.bfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
- bmpfile.biInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmpfile.biInfo.bmiHeader.biWidth = width;
- bmpfile.biInfo.bmiHeader.biHeight = height;
- bmpfile.biInfo.bmiHeader.biPlanes = 1;
- bmpfile.biInfo.bmiHeader.biBitCount = bitCountPerPix;
- bmpfile.biInfo.bmiHeader.biCompression = 0;
- bmpfile.biInfo.bmiHeader.biSizeImage = filesize;
- bmpfile.biInfo.bmiHeader.biXPelsPerMeter = 0;
- bmpfile.biInfo.bmiHeader.biYPelsPerMeter = 0;
- bmpfile.biInfo.bmiHeader.biClrUsed = 0;
- bmpfile.biInfo.bmiHeader.biClrImportant = 0;
- fwrite(&(bmpfile.bfHeader), sizeof(BITMAPFILEHEADER), 1, fp);
- fwrite(&(bmpfile.biInfo.bmiHeader), sizeof(BITMAPINFOHEADER), 1, fp);
- fwrite(pData,filesize,1, fp);
- // U8 *pEachLinBuf = (U8*)malloc(bmppitch);
- // memset(pEachLinBuf, 0, bmppitch);
- // U8 BytePerPix = bitCountPerPix >> 3;
- // U32 pitch = width * BytePerPix;
- // if(pEachLinBuf)
- // {
- // int h,w;
- // for(h = height-1; h >= 0; h--)
- // {
- // for(w = 0; w < width; w++)
- // {
- // //copy by a pixel
- // pEachLinBuf[w*BytePerPix+0] = pData[h*pitch + w*BytePerPix + 0];
- // pEachLinBuf[w*BytePerPix+1] = pData[h*pitch + w*BytePerPix + 1];
- // pEachLinBuf[w*BytePerPix+2] = pData[h*pitch + w*BytePerPix + 2];
- // }
- // fwrite(pEachLinBuf, bmppitch, 1, fp);
- //
- // }
- // free(pEachLinBuf);
- // }
- fclose(fp);
- return 1;
- }
/*
* main.c
*
* Created on: Apr 25, 2016
* Author: anzyelay
*/
#include <unistd.h>
#include <linux/fb.h>
#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 "bmp.h"
#define CAMERA_DEVICE "/dev/video0"
#define FB_DEVICE "/dev/fb0"
#define VIDEO_WIDTH 640
#define VIDEO_HEIGHT 480
#define BUFFER_COUNT 4
typedef struct VideoBuffer {
void *start;
size_t length;
} VideoBuffer;
VideoBuffer framebuf[BUFFER_COUNT];
//查表法,把YUV422转换为RGB32
void process(unsigned long *rgb_buf, unsigned char *v_buf)
{
int r,g,b;
int u,v;
int y[2];
int rv,guv,bu,i;
unsigned int *fb_buf = (unsigned int *)rgb_buf;
y[0]=(int)*v_buf;
v=(int)*(v_buf+1);
y[1]=(int)*(v_buf+2);
u=(int)*(v_buf+3);
rv=rvarrxyp[v];
guv=guarrxyp[u]+gvarrxyp[v];
bu=buarrxyp[u];
for(i=0;i<2;i++){
r=y[i]+rv;
g=y[i]-guv;
b=y[i]+bu;
if (r>255) r=255;
if (r<0) r=0;
if (g>255) g=255;
if (g<0) g=0;
if (b>255) b=255;
if (b<0) b=0;
*(fb_buf+i)=(b<<16)+(g<<8)+r;
}
}
int main()
{
int i, ret;
// 打开摄像头设备
int fd;
fd = open(CAMERA_DEVICE, O_RDWR, 0);
if (fd < 0) {
printf("Open %s failed\n", CAMERA_DEVICE);
return -1;
}
// 获取驱动信息
struct v4l2_capability cap;
ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
if (ret < 0) {
printf("VIDIOC_QUERYCAP failed (%d)\n", ret);
goto __error1;
}
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: %u.%u.%u\n", (cap.version>>16)&0XFF, (cap.version>>8)&0XFF,cap.version&0XFF);
printf(" capabilities: %08X\n", cap.capabilities);
// 设置视频格式
struct v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
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.field = V4L2_FIELD_INTERLACED;
ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
if (ret < 0) {
printf("VIDIOC_S_FMT failed (%d)\n", ret);
goto __error1;
}
//获取视频格式(原因是设置视频格式时如果有错误,VIDIOC_S_FMT时会自动转换成合作的格式,所以再获取一次)
ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
if (ret < 0) {
printf("VIDIOC_G_FMT failed (%d)\n", ret);
goto __error1;
}
// Print Stream Format
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);
//-----------------------------------------------
//请求分配内存
struct v4l2_requestbuffers reqbuf;
reqbuf.count = BUFFER_COUNT;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd , VIDIOC_REQBUFS, &reqbuf);//在内核虚拟地址空间中申请reqbuf.count个连续的内存
if(ret < 0) {
printf("VIDIOC_REQBUFS failed (%d)\n", ret);
goto __error1;
}
struct v4l2_buffer buf;
for (i = 0; i < reqbuf.count; i++)
{
buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
//根据buf.index询访内存为后面的映射做准备(本质就是设置buf.m.offset+=buf.length偏移)
ret = ioctl(fd , VIDIOC_QUERYBUF, &buf);
if(ret < 0) {
printf("VIDIOC_QUERYBUF (%d) failed (%d)\n", i, ret);
goto __error1;
}
//映射到用户空间
//就是将之前内核分配的视频缓冲(VIDIOC_REQBUFS)映射到用户空间,这样用户空间就可以直接读取内核扑获的视频数据
//buf.m.offset表示要对内核中的哪个video buffer进行映射操作
framebuf[i].length = buf.length;
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));
ret = -1;
goto __error1;
}
//内存入队列
ret = ioctl(fd , VIDIOC_QBUF, &buf);
if (ret < 0) {
printf("VIDIOC_QBUF (%d) failed (%d)\n", i, ret);
goto __error2;
}
printf("Frame buffer %d: address=0x%x, length=%d\n", i,
(unsigned long)framebuf[i].start,
(unsigned int)framebuf[i].length);
}
//--------------------------------------
// 启动视频流
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_STREAMON, &type);
if (ret < 0) {
printf("VIDIOC_STREAMON failed (%d)\n", ret);
goto __error2;
}
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
int x,y;
int fd_fb;
long int screen_size = 0;
unsigned long *fbp32 = NULL;
//打开LCD设备
fd_fb = open(FB_DEVICE, O_RDWR);
if (fd_fb < 0)
{
printf("Error: cannot open framebuffer device.\n");
goto __error2;
}
if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &finfo))
{
printf("Error reading fixed information.\n");
goto __error3;
}
//获取LCD属性信息
if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &vinfo))
{
printf("Error 2 reading variable information.\n");
goto __error3;
}
//一屏的字节数
screen_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
printf("LCD: %dx%d, %dbpp, screen_size = %ld\n",
vinfo.xres,
vinfo.yres,
vinfo.bits_per_pixel,
screen_size );
//映射framebuffer到用户空间
fbp32 = (unsigned long *)mmap(0, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
if (fbp32 == MAP_FAILED)
{
printf("Error: failed to map framebuffer device to memory.\n");
goto __error3;
}
printf("start camera testing...\n");
//开始视频显示
// while(1)
unsigned long *picdata = (unsigned long *)malloc(fmt.fmt.pix.height*fmt.fmt.pix.width*4);
memset(picdata,0,fmt.fmt.pix.height*fmt.fmt.pix.width*4);
for(i=0;i<1;i++)
{
memset(&buf,0,sizeof(buf));
buf.index = 0;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
//内存空间出队列
ret = ioctl(fd, VIDIOC_DQBUF, &buf);
if (ret < 0)
{
printf("VIDIOC_DQBUF failed (%d)\n", ret);
break;
}
if(vinfo.bits_per_pixel == 32)
{
//yuv422 两个像素占4个字节(Y0,V,Y1,U),两个像素共用一个UV对,总字节数为W*H*2,
//而RGB32则正好两个像素是一个LONG型对齐,以LONG为单位一次可计算两个像素点,之后framebuf自增4个字节地址指向一两个像素点
for(y = 0; y < fmt.fmt.pix.height; y++)
{
for(x = 0; x < fmt.fmt.pix.width/2; x++)
{
//YUV422转换为RGB32
// process(fbp32 + y*vinfo.xres + x,
// (U8 *)framebuf[buf.index].start + (y*fmt.fmt.pix.width+x)*2);
//由于是以long为基数自增,所以一行long数为:width(long)=width(int)/2
process((picdata + y*fmt.fmt.pix.width/2 + x),
(U8 *)framebuf[buf.index].start + y*fmt.fmt.pix.width*2+x*4);
}
}
}
// 内存重新入队列
ret = ioctl(fd, VIDIOC_QBUF, &buf);
if (ret < 0)
{
printf("VIDIOC_QBUF failed (%d)\n", ret);
break;
}
}//while(1)
/*save image picture captured*/
char picname[100];
sprintf(picname,"./niu_%d*%d.bmp",fmt.fmt.pix.width,fmt.fmt.pix.height);
GenBmpFile((U8 *)picdata,32,fmt.fmt.pix.width,fmt.fmt.pix.height,picname);
//释放fbp32资源
munmap(fbp32, screen_size);
__error3://关闭fd_fb设备
close(fd_fb);
__error2://释放framebuf资源
for (i=0; i< 4; i++)
{
munmap(framebuf[i].start, framebuf[i].length);
}
__error1://关闭fd设备
close(fd);
return ret;
}
//------------save image picture captured--------///
int GenBmpFile(U8 *pData, U8 bitCountPerPix, U32 width, U32 height, const char *filename)
{
FILE *fp = fopen(filename, "wb");
if(!fp)
{
printf("fopen failed : %s, %d\n", __FILE__, __LINE__);
return 0;
}
U32 bmppitch = ((width*bitCountPerPix + 31) >> 5) << 2;
U32 filesize = bmppitch*height;
BITMAPFILE bmpfile;
bmpfile.bfHeader.bfType = 0x4D42;
bmpfile.bfHeader.bfSize = filesize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpfile.bfHeader.bfReserved1 = 0;
bmpfile.bfHeader.bfReserved2 = 0;
bmpfile.bfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpfile.biInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpfile.biInfo.bmiHeader.biWidth = width;
bmpfile.biInfo.bmiHeader.biHeight = height;
bmpfile.biInfo.bmiHeader.biPlanes = 1;
bmpfile.biInfo.bmiHeader.biBitCount = bitCountPerPix;
bmpfile.biInfo.bmiHeader.biCompression = 0;
bmpfile.biInfo.bmiHeader.biSizeImage = filesize;
bmpfile.biInfo.bmiHeader.biXPelsPerMeter = 0;
bmpfile.biInfo.bmiHeader.biYPelsPerMeter = 0;
bmpfile.biInfo.bmiHeader.biClrUsed = 0;
bmpfile.biInfo.bmiHeader.biClrImportant = 0;
fwrite(&(bmpfile.bfHeader), sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&(bmpfile.biInfo.bmiHeader), sizeof(BITMAPINFOHEADER), 1, fp);
fwrite(pData,filesize,1, fp);
// U8 *pEachLinBuf = (U8*)malloc(bmppitch);
// memset(pEachLinBuf, 0, bmppitch);
// U8 BytePerPix = bitCountPerPix >> 3;
// U32 pitch = width * BytePerPix;
// if(pEachLinBuf)
// {
// int h,w;
// for(h = height-1; h >= 0; h--)
// {
// for(w = 0; w < width; w++)
// {
// //copy by a pixel
// pEachLinBuf[w*BytePerPix+0] = pData[h*pitch + w*BytePerPix + 0];
// pEachLinBuf[w*BytePerPix+1] = pData[h*pitch + w*BytePerPix + 1];
// pEachLinBuf[w*BytePerPix+2] = pData[h*pitch + w*BytePerPix + 2];
// }
// fwrite(pEachLinBuf, bmppitch, 1, fp);
//
// }
// free(pEachLinBuf);
// }
fclose(fp);
return 1;
}
bmp.h
- /*
- * bmp.h
- *
- * Created on: Apr 26, 2016
- * Author: anzyelay
- */
- #ifndef BMP_H_
- #define BMP_H_
- #pragma pack(push, 1)
- typedef unsigned char U8;
- typedef unsigned short U16;
- typedef unsigned int U32;
- typedef struct tagBITMAPFILEHEADER
- {
- U16 bfType;
- U32 bfSize;
- U16 bfReserved1;
- U16 bfReserved2;
- U32 bfOffBits;
- } BITMAPFILEHEADER;
- typedef struct tagBITMAPINFOHEADER
- {
- U32 biSize;
- U32 biWidth;
- U32 biHeight;
- U16 biPlanes;
- U16 biBitCount;
- U32 biCompression;
- U32 biSizeImage;
- U32 biXPelsPerMeter;
- U32 biYPelsPerMeter;
- U32 biClrUsed;
- U32 biClrImportant;
- } BITMAPINFOHEADER;
- typedef struct tagRGBQUAD
- {
- U8 rgbBlue;
- U8 rgbGreen;
- U8 rgbRed;
- U8 rgbReserved;
- } RGBQUAD;
- typedef struct tagBITMAPINFO
- {
- BITMAPINFOHEADER bmiHeader;
- RGBQUAD bmiColors[1];
- } BITMAPINFO;
- typedef struct tagBITMAP
- {
- BITMAPFILEHEADER bfHeader;
- BITMAPINFO biInfo;
- }BITMAPFILE;
- #pragma pack(pop)
- int GenBmpFile(U8 *pData, U8 bitCountPerPix, U32 width, U32 height, const char *filename);
- //YUV422转换为RGB32表
- const int rvarrxyp[]={
- -180,-179,-177,-176,-175,-173,-172,-170,-169,-167,-166,-165,-163,-162,-160,-159,-158,-156,-155,-153,-152,-151,
- -149,-148,-146,-145,-144,-142,-141,-139,-138,-137,-135,-134,-132,-131,-129,-128,-127,-125,-124,-122,-121,-120,
- -118,-117,-115,-114,-113,-111,-110,-108,-107,-106,-104,-103,-101,-100,-99,-97,-96,-94,-93,-91,-90,-89,-87,-86,
- -84,-83,-82,-80,-79,-77,-76,-75,-73,-72,-70,-69,-68,-66,-65,-63,-62,-61,-59,-58,-56,-55,-53,-52,-51,-49,-48,
- -46,-45,-44,-42,-41,-39,-38,-37,-35,-34,-32,-31,-30,-28,-27,-25,-24,-23,-21,-20,-18,-17,-15,-14,-13,-11,-10,
- -8,-7,-6,-4,-3,-1,0,1,3,4,6,7,8,10,11,13,14,15,17,18,20,21,23,24,25,27,28,30,31,32,34,35,37,38,39,41,42,44,45,
- 46,48,49,51,52,53,55,56,58,59,61,62,63,65,66,68,69,70,72,73,75,76,77,79,80,82,83,84,86,87,89,90,91,93,94,96,
- 97,99,100,101,103,104,106,107,108,110,111,113,114,115,117,118,120,121,122,124,125,127,128,129,131,132,134,135,
- 137,138,139,141,142,144,145,146,148,149,151,152,153,155,156,158,159,160,162,163,165,166,167,169,170,172,173,175,
- 176,177,179};
- const int guarrxyp[]={
- -44,-44,-44,-43,-43,-42,-42,-42,-41,-41,-41,-40,-40,-40,-39,-39,-39,-38,-38,-38,-37,-37,-37,-36,-36,-36,-35,-35,
- -35,-34,-34,-34,-33,-33,-32,-32,-32,-31,-31,-31,-30,-30,-30,-29,-29,-29,-28,-28,-28,-27,-27,-27,-26,-26,-26,-25,
- -25,-25,-24,-24,-23,-23,-23,-22,-22,-22,-21,-21,-21,-20,-20,-20,-19,-19,-19,-18,-18,-18,-17,-17,-17,-16,-16,-16,
- -15,-15,-15,-14,-14,-13,-13,-13,-12,-12,-12,-11,-11,-11,-10,-10,-10,-9,-9,-9,-8,-8,-8,-7,-7,-7,-6,-6,-6,-5,-5,-4,
- -4,-4,-3,-3,-3,-2,-2,-2,-1,-1,-1,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,6,7,7,7,8,8,8,9,9,9,10,10,10,11,11,11,12,12,
- 12,13,13,13,14,14,15,15,15,16,16,16,17,17,17,18,18,18,19,19,19,20,20,20,21,21,21,22,22,22,23,23,23,24,24,25,25,25,
- 26,26,26,27,27,27,28,28,28,29,29,29,30,30,30,31,31,31,32,32,32,33,33,34,34,34,35,35,35,36,36,36,37,37,37,38,38,38,
- 39,39,39,40,40,40,41,41,41,42,42,42,43,43,44,44};
- const int gvarrxyp[]={
- -92,-91,-90,-90,-89,-88,-87,-87,-86,-85,-85,-84,-83,-82,-82,-81,-80,-80,-79,-78,-77,-77,-76,-75,-75,-74,-73,-72,
- -72,-71,-70,-70,-69,-68,-67,-67,-66,-65,-65,-64,-63,-62,-62,-61,-60,-60,-59,-58,-57,-57,-56,-55,-54,-54,-53,-52,-52,
- -51,-50,-49,-49,-48,-47,-47,-46,-45,-44,-44,-43,-42,-42,-41,-40,-39,-39,-38,-37,-37,-36,-35,-34,-34,-33,-32,-32,-31,
- -30,-29,-29,-28,-27,-27,-26,-25,-24,-24,-23,-22,-22,-21,-20,-19,-19,-18,-17,-16,-16,-15,-14,-14,-13,-12,-11,-11,-10,
- -9,-9,-8,-7,-6,-6,-5,-4,-4,-3,-2,-1,-1,0,1,1,2,3,4,4,5,6,6,7,8,9,9,10,11,11,12,13,14,14,15,16,16,17,18,19,19,20,21,
- 22,22,23,24,24,25,26,27,27,28,29,29,30,31,32,32,33,34,34,35,36,37,37,38,39,39,40,41,42,42,43,44,44,45,46,47,47,48,49,
- 49,50,51,52,52,53,54,54,55,56,57,57,58,59,60,60,61,62,62,63,64,65,65,66,67,67,68,69,70,70,71,72,72,73,74,75,75,76,77,
- 77,78,79,80,80,81,82,82,83,84,85,85,86,87,87,88,89,90,90,91};
- const int buarrxyp[]={
- -228,-226,-224,-222,-221,-219,-217,-215,-213,-212,-210,-208,-206,-205,-203,-201,-199,-197,-196,-194,-192,-190,-189,
- -187,-185,-183,-181,-180,-178,-176,-174,-173,-171,-169,-167,-165,-164,-162,-160,-158,-157,-155,-153,-151,-149,-148,
- -146,-144,-142,-141,-139,-137,-135,-133,-132,-130,-128,-126,-125,-123,-121,-119,-117,-116,-114,-112,-110,-109,-107,
- -105,-103,-101,-100,-98,-96,-94,-93,-91,-89,-87,-85,-84,-82,-80,-78,-76,-75,-73,-71,-69,-68,-66,-64,-62,-60,-59,-57,
- -55,-53,-52,-50,-48,-46,-44,-43,-41,-39,-37,-36,-34,-32,-30,-28,-27,-25,-23,-21,-20,-18,-16,-14,-12,-11,-9,-7,-5,-4,
- -2,0,2,4,5,7,9,11,12,14,16,18,20,21,23,25,27,28,30,32,34,36,37,39,41,43,44,46,48,50,52,53,55,57,59,60,62,64,66,68,69,
- 71,73,75,76,78,80,82,84,85,87,89,91,93,94,96,98,100,101,103,105,107,109,110,112,114,116,117,119,121,123,125,126,128,
- 130,132,133,135,137,139,141,142,144,146,148,149,151,153,155,157,158,160,162,164,165,167,169,171,173,174,176,178,180,
- 181,183,185,187,189,190,192,194,196,197,199,201,203,205,206,208,210,212,213,215,217,219,221,222,224,226};
- #endif /* BMP_H_ */
/*
* bmp.h
*
* Created on: Apr 26, 2016
* Author: anzyelay
*/
#ifndef BMP_H_
#define BMP_H_
#pragma pack(push, 1)
typedef unsigned char U8;
typedef unsigned short U16;
typedef unsigned int U32;
typedef struct tagBITMAPFILEHEADER
{
U16 bfType;
U32 bfSize;
U16 bfReserved1;
U16 bfReserved2;
U32 bfOffBits;
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER
{
U32 biSize;
U32 biWidth;
U32 biHeight;
U16 biPlanes;
U16 biBitCount;
U32 biCompression;
U32 biSizeImage;
U32 biXPelsPerMeter;
U32 biYPelsPerMeter;
U32 biClrUsed;
U32 biClrImportant;
} BITMAPINFOHEADER;
typedef struct tagRGBQUAD
{
U8 rgbBlue;
U8 rgbGreen;
U8 rgbRed;
U8 rgbReserved;
} RGBQUAD;
typedef struct tagBITMAPINFO
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;
typedef struct tagBITMAP
{
BITMAPFILEHEADER bfHeader;
BITMAPINFO biInfo;
}BITMAPFILE;
#pragma pack(pop)
int GenBmpFile(U8 *pData, U8 bitCountPerPix, U32 width, U32 height, const char *filename);
//YUV422转换为RGB32表
const int rvarrxyp[]={
-180,-179,-177,-176,-175,-173,-172,-170,-169,-167,-166,-165,-163,-162,-160,-159,-158,-156,-155,-153,-152,-151,
-149,-148,-146,-145,-144,-142,-141,-139,-138,-137,-135,-134,-132,-131,-129,-128,-127,-125,-124,-122,-121,-120,
-118,-117,-115,-114,-113,-111,-110,-108,-107,-106,-104,-103,-101,-100,-99,-97,-96,-94,-93,-91,-90,-89,-87,-86,
-84,-83,-82,-80,-79,-77,-76,-75,-73,-72,-70,-69,-68,-66,-65,-63,-62,-61,-59,-58,-56,-55,-53,-52,-51,-49,-48,
-46,-45,-44,-42,-41,-39,-38,-37,-35,-34,-32,-31,-30,-28,-27,-25,-24,-23,-21,-20,-18,-17,-15,-14,-13,-11,-10,
-8,-7,-6,-4,-3,-1,0,1,3,4,6,7,8,10,11,13,14,15,17,18,20,21,23,24,25,27,28,30,31,32,34,35,37,38,39,41,42,44,45,
46,48,49,51,52,53,55,56,58,59,61,62,63,65,66,68,69,70,72,73,75,76,77,79,80,82,83,84,86,87,89,90,91,93,94,96,
97,99,100,101,103,104,106,107,108,110,111,113,114,115,117,118,120,121,122,124,125,127,128,129,131,132,134,135,
137,138,139,141,142,144,145,146,148,149,151,152,153,155,156,158,159,160,162,163,165,166,167,169,170,172,173,175,
176,177,179};
const int guarrxyp[]={
-44,-44,-44,-43,-43,-42,-42,-42,-41,-41,-41,-40,-40,-40,-39,-39,-39,-38,-38,-38,-37,-37,-37,-36,-36,-36,-35,-35,
-35,-34,-34,-34,-33,-33,-32,-32,-32,-31,-31,-31,-30,-30,-30,-29,-29,-29,-28,-28,-28,-27,-27,-27,-26,-26,-26,-25,
-25,-25,-24,-24,-23,-23,-23,-22,-22,-22,-21,-21,-21,-20,-20,-20,-19,-19,-19,-18,-18,-18,-17,-17,-17,-16,-16,-16,
-15,-15,-15,-14,-14,-13,-13,-13,-12,-12,-12,-11,-11,-11,-10,-10,-10,-9,-9,-9,-8,-8,-8,-7,-7,-7,-6,-6,-6,-5,-5,-4,
-4,-4,-3,-3,-3,-2,-2,-2,-1,-1,-1,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,6,7,7,7,8,8,8,9,9,9,10,10,10,11,11,11,12,12,
12,13,13,13,14,14,15,15,15,16,16,16,17,17,17,18,18,18,19,19,19,20,20,20,21,21,21,22,22,22,23,23,23,24,24,25,25,25,
26,26,26,27,27,27,28,28,28,29,29,29,30,30,30,31,31,31,32,32,32,33,33,34,34,34,35,35,35,36,36,36,37,37,37,38,38,38,
39,39,39,40,40,40,41,41,41,42,42,42,43,43,44,44};
const int gvarrxyp[]={
-92,-91,-90,-90,-89,-88,-87,-87,-86,-85,-85,-84,-83,-82,-82,-81,-80,-80,-79,-78,-77,-77,-76,-75,-75,-74,-73,-72,
-72,-71,-70,-70,-69,-68,-67,-67,-66,-65,-65,-64,-63,-62,-62,-61,-60,-60,-59,-58,-57,-57,-56,-55,-54,-54,-53,-52,-52,
-51,-50,-49,-49,-48,-47,-47,-46,-45,-44,-44,-43,-42,-42,-41,-40,-39,-39,-38,-37,-37,-36,-35,-34,-34,-33,-32,-32,-31,
-30,-29,-29,-28,-27,-27,-26,-25,-24,-24,-23,-22,-22,-21,-20,-19,-19,-18,-17,-16,-16,-15,-14,-14,-13,-12,-11,-11,-10,
-9,-9,-8,-7,-6,-6,-5,-4,-4,-3,-2,-1,-1,0,1,1,2,3,4,4,5,6,6,7,8,9,9,10,11,11,12,13,14,14,15,16,16,17,18,19,19,20,21,
22,22,23,24,24,25,26,27,27,28,29,29,30,31,32,32,33,34,34,35,36,37,37,38,39,39,40,41,42,42,43,44,44,45,46,47,47,48,49,
49,50,51,52,52,53,54,54,55,56,57,57,58,59,60,60,61,62,62,63,64,65,65,66,67,67,68,69,70,70,71,72,72,73,74,75,75,76,77,
77,78,79,80,80,81,82,82,83,84,85,85,86,87,87,88,89,90,90,91};
const int buarrxyp[]={
-228,-226,-224,-222,-221,-219,-217,-215,-213,-212,-210,-208,-206,-205,-203,-201,-199,-197,-196,-194,-192,-190,-189,
-187,-185,-183,-181,-180,-178,-176,-174,-173,-171,-169,-167,-165,-164,-162,-160,-158,-157,-155,-153,-151,-149,-148,
-146,-144,-142,-141,-139,-137,-135,-133,-132,-130,-128,-126,-125,-123,-121,-119,-117,-116,-114,-112,-110,-109,-107,
-105,-103,-101,-100,-98,-96,-94,-93,-91,-89,-87,-85,-84,-82,-80,-78,-76,-75,-73,-71,-69,-68,-66,-64,-62,-60,-59,-57,
-55,-53,-52,-50,-48,-46,-44,-43,-41,-39,-37,-36,-34,-32,-30,-28,-27,-25,-23,-21,-20,-18,-16,-14,-12,-11,-9,-7,-5,-4,
-2,0,2,4,5,7,9,11,12,14,16,18,20,21,23,25,27,28,30,32,34,36,37,39,41,43,44,46,48,50,52,53,55,57,59,60,62,64,66,68,69,
71,73,75,76,78,80,82,84,85,87,89,91,93,94,96,98,100,101,103,105,107,109,110,112,114,116,117,119,121,123,125,126,128,
130,132,133,135,137,139,141,142,144,146,148,149,151,153,155,157,158,160,162,164,165,167,169,171,173,174,176,178,180,
181,183,185,187,189,190,192,194,196,197,199,201,203,205,206,208,210,212,213,215,217,219,221,222,224,226};
#endif /* BMP_H_ */
此代码在PC机上可以正常显示,但下到开发板老是出现
VIDIOC_S_FMT failed -1
此错误,
检查 发现是 设置格式错误,百度各种说法,有说是pixelformat格式不对的,但在PC机上却是正常的,不管了,先换换,把VIDIOC_S_FMT 和 VIDIOC_G_FMT 反下,先查询支持什么格式再设置,
更改如下
- // 设置视频格式
- struct v4l2_format <span style="color:#FF0000;">fmt1</span>,fmt; //fmt1临时查询格式使用
- memset(&fmt1, 0, sizeof(fmt1));
- memset(&fmt, 0, sizeof(fmt));
- fmt1.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;</span>
- //先获取视频格式
- ret = ioctl(fd, VIDIOC_G_FMT, &fmt1);
- if (ret < 0) {
- printf("VIDIOC_G_FMT failed (%d)\n", ret);
- goto __error1;
- }
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = VIDEO_WIDTH;
- fmt.fmt.pix.height = VIDEO_HEIGHT;
- fmt.fmt.pix.pixelformat = fmt1.fmt.pix.pixelformat; //把上面查询到地格式赋给要设置的变量
- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
- ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
- if (ret < 0) {
- printf("VIDIOC_S_FMT failed (%d)\n", ret);
- goto __error1;
- }
// 设置视频格式
struct v4l2_format <span style="color:#FF0000;">fmt1</span>,fmt; //fmt1临时查询格式使用
memset(&fmt1, 0, sizeof(fmt1));
memset(&fmt, 0, sizeof(fmt));
fmt1.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;</span>
//先获取视频格式
ret = ioctl(fd, VIDIOC_G_FMT, &fmt1);
if (ret < 0) {
printf("VIDIOC_G_FMT failed (%d)\n", ret);
goto __error1;
}
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = VIDEO_WIDTH;
fmt.fmt.pix.height = VIDEO_HEIGHT;
fmt.fmt.pix.pixelformat = fmt1.fmt.pix.pixelformat; //把上面查询到地格式赋给要设置的变量
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
if (ret < 0) {
printf("VIDIOC_S_FMT failed (%d)\n", ret);
goto __error1;
}
编译在PC上可正常能过,调试信息时: pixelformat:
YUYV
下到板子上也能正常运行下去了,调试信息:pixelformat: MJPG
输出格式居然不一样。。。。。。
终于知道错误原因了,应该是开发板和电脑上的UVC驱动版本不一样导致输出的支持格式不一。优化下代码,转MJPG格式输出,MJPG保存图片函数:
//保存为图片 test.jpg
int GenJpgFile(VideoBuffer *buffers,const char *filename){
FILE *fp = NULL;
fp = fopen(filename, "w");
if(fp != NULL){
fwrite(buffers->start, 1,buffers->length, fp);
sync();
fclose(fp);
return 1;
}
return 0;
}
-
顶
- 0
-
踩
- 0
- 上一篇linux error note
- 下一篇vim一些快捷键
我的同类文章
- •RGB565,RGB24,YUV2016-09-22
- •Linux UVC driver 独立交叉编译记录2016-09-06
- •记录USB摄像头的几个问题2016-09-13
- •linux 下USB 摄像头的使用说明2016-09-02
参考知识库
- Linux环境C语言编程基础
- 《C语言/C++学习指南》Linux开发篇
- I2C总线和触摸屏驱动移植实战-linux驱动开发第9部分
- 2.6 内核I2C驱动框架
-
内存这个大话题-4.1.C语言高级专题第一部分
- V4L2 soc-camera 子系统
- linux系统V4L2架构OV3640摄像头视频捕获保存图片jpg格式
- Camera driver&V4L2驱动架构介绍
- 嵌入式Linux下Camera编程--V4L2
- 深入浅出camera v4l2理解
暂无评论