问题遇到的现象和发生背景
在ubuntu上使用v4l2采集一帧.jpg格式的图片,采集方式设置的是
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
按理说保存.jpg格式图片应该可以显示,但显示失败
问题相关代码,请勿粘贴截图
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <memory.h>
#include <errno.h>
#include <sys/mman.h>
#include <string.h>
#include <jpeglib.h>
//using namespace std;
struct buffer
{
void * start;
unsigned int length;
} * buffers;
int main(void)
{
//1.打开设备
int fd = open("/dev/video0", O_RDWR);
if(fd < 0)
{
perror("打开设备失败");
return -1;
}
else
printf("1.opening succeeded\n\n");
//2.get camera capabilities
struct v4l2_capability cap;
memset(&cap, 0, sizeof(cap));
/* 获取设备支持的操作 */
if(ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0){
printf("no camera");
return -1;
}
else
printf("2.get camera\n\n");
//获取成功,检查是否有视频捕获功能
if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)){
printf("can not support cap");
return -1;
}
/* streaming I/O ioctls */
if(!(cap.capabilities & V4L2_CAP_STREAMING)){
printf("can not support steaming");
return -1;
}
struct v4l2_fmtdesc v4fmt; //根据对应的结构体,定义相应的结构体对象
v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //结构体成员type需要初始化定义,v4l2_buf_type是个枚举类型
printf("video support format:\n");
int i=0;
while(1)
{
v4fmt.index = i++;
int ret = ioctl(fd, VIDIOC_ENUM_FMT, &v4fmt);
if(ret < 0)
{
break;
}
printf("index=%d\n", v4fmt.index); //索引设备的第几个格式
printf("flags=%d\n", v4fmt.flags);//标号
printf("description=%s\n", v4fmt.description);
unsigned char *p = (unsigned char *)&v4fmt.pixelformat; //结构体成员pixelformat有4个字节,构建一个指针一个一个打
printf("pixelformat=%c%c%c%c\n", p[0],p[1],p[2],p[3]);
printf("reserved=%d\n\n", v4fmt.reserved[0]);
}
//3.set capture type
struct v4l2_format fmt;
//memset(&fmt, 0, sizeof(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_MJPEG;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
/* 设置设备捕获视频的格式 */
if(ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)
{
printf("formatting failed");
return -1;
}
else
printf("3.formatting succeeded\n");
memset(&fmt, 0, sizeof(fmt)); //清空结构体
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)//G—FMT 获取采集格式
{
perror("获取格式失败");
}
else
{
printf("Current data format information:\nwidth:%d\nheight:%d\n",fmt.fmt.pix.width,fmt.fmt.pix.height);
unsigned char *fp = (unsigned char *)&fmt.fmt.pix.pixelformat; //结构体成员pixelformat有4个字节,构建一个指针一个一个打
printf("pixelformat=%c%c%c%c\n\n", fp[0],fp[1],fp[2],fp[3]);
}
//4.request kernel buffer
struct v4l2_requestbuffers req;
memset(&req,0,sizeof(req));
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.count = 4;
req.memory = V4L2_MEMORY_MMAP ;
if(ioctl(fd, VIDIOC_REQBUFS, &req) < 0)
{
perror("申请队列空间失败");
}
else
printf("4.requesting buffer succeeded\n\n");
//5.map to user space
buffers = (struct buffer*)calloc(req.count, sizeof(*buffers));
struct v4l2_buffer buf;
for (int numBufs = 0; numBufs < req.count; numBufs++)
{
memset( &buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1)
{
printf("query buffer error");
return -1;
}
buffers[numBufs].length = buf.length;
buffers[numBufs].start = mmap(NULL, buf.length,PROT_READ | PROT_WRITE,MAP_SHARED,fd, buf.m.offset);
if (buffers[numBufs].start == MAP_FAILED)
{
printf("buffer map error");
return -1;
}
else
printf("5. No.%d buffer maping succeeded\n\n",numBufs);
if(ioctl(fd, VIDIOC_QBUF, &buf) < 0)
{
perror("放回失败");
}
}
//6.starting capture
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
//打开设备视频流
if(ioctl(fd, VIDIOC_STREAMON, &type) < 0)
{
printf("cap failed");
return -1;
}
else
printf("6.cap succeeded\n\n");
//while(1)
//7.read capture data video datas in buffers[numBufs].start
struct v4l2_buffer buf2; ;
buf2.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf2.memory= V4L2_MEMORY_MMAP;
if(ioctl(fd,VIDIOC_DQBUF,&buf2)<0)
{
printf("read data error");
}
else
printf("7.reading viedo data succeeded\n\n");
/*8.save an image to a file
{
read_JPEG_file (buffers[buf.index], rgbdata, buf.length);
rgb2mat(rgbdata,640,480);
}*/
FILE *file = fopen("first.jpg","w+");
if(file == NULL)
{
printf("opening file error \n");
}
int ret;
ret =fwrite(buffers[0].start,buf2.length,1,file);
if(ret == 1)
{
printf("8.writing data to file succeeded\n\n");
}
ret =fclose(file);
if(ret == 0)
{
printf("file closed\n");
}
if(ioctl(fd,VIDIOC_QBUF,&buf2)<0)
{
printf("colsing kernel buffer error");
}
/*
//9.stopping capture
if(ioctl(fd,VIDIOC_STREAMOFF,&type)<0)
{
printf("stopping cap error");
}
else
printf("9.stop cap\n");
*/
//10.关闭设备
close(fd);
return 0;
}
运行结果及报错内容
我的解答思路和尝试过的方法
我想要达到的结果
请问这个怎么改,或哪里错了么