v4l2 camera测试程序 保存成图片
本文章已收录于:
版权声明:本文为博主原创文章,转载请注明转载地址。
使用的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一些快捷键
我的同类文章
http://blog.csdn.net
- •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理解
更多资料请参考:
猜你在找
核心技术类目
全部主题
Hadoop
AWS
移动游戏
Java
Android
iOS
Swift
智能硬件
Docker
OpenStack
VPN
Spark
ERP
IE10
Eclipse
CRM
JavaScript
数据库
Ubuntu
NFC
WAP
jQuery
BI
HTML5
Spring
Apache
.NET
API
HTML
SDK
IIS
Fedora
XML
LBS
Unity
Splashtop
UML
components
Windows Mobile
Rails
QEMU
KDE
Cassandra
CloudStack
FTC
coremail
OPhone
CouchBase
云计算
iOS6
Rackspace
Web App
SpringSide
Maemo
Compuware
大数据
aptech
Perl
Tornado
Ruby
Hibernate
ThinkPHP
HBase
Pure
Solr
Angular
Cloud Foundry
Redis
Scala
Django
Bootstrap
暂无评论