zhbliulu 2022-03-13 10:37 采纳率: 0%
浏览 92

在ubuntu上使用v4l2采集一帧图片成功,显示图片报错

问题遇到的现象和发生背景

在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;

}

运行结果及报错内容

img

img

我的解答思路和尝试过的方法
我想要达到的结果

请问这个怎么改,或哪里错了么

  • 写回答

1条回答 默认 最新

  • 「已注销」 2022-03-13 15:25
    关注

    你的设置应该不正确

    评论

报告相同问题?

问题事件

  • 创建了问题 3月13日

悬赏问题

  • ¥50 windows的SFTP服务器如何能批量同步用户信息?
  • ¥15 centos7.9升级python3.0的问题
  • ¥15 如何解决调试dev-出++5.11不成功问题
  • ¥15 安装CentOS6时卡住
  • ¥20 关于#监控系统#的问题,如何解决?(相关搜索:系统软件)
  • ¥20 c语言写的8051单片机存储器mt29的模块程序
  • ¥60 求直线方程 使平面上n个点在直线同侧并且距离总和最小
  • ¥50 java算法,给定试题的难度数量(简单,普通,困难),和试题类型数量(单选,多选,判断),以及题库中各种类型的题有多少道,求能否随机抽题。
  • ¥50 rk3588板端推理
  • ¥250 opencv怎么去掉 数字0中间的斜杠。