Linux下通过V4L2从USB相机取MJPEG视频流

news/2025/3/15 12:01:48/

避免以后要用到,备用

#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <linux/videodev2.h>
#include<sys/ioctl.h>
#include <setjmp.h>
#include <unistd.h>#define CAM_DEV "/dev/video14"
#define   WIDTH   1920                       // 图片的宽度
#define   HEIGHT  1080                       // 图片的高度
#define  NB_BUFFER  4   //memory block number
struct pic_data 
{unsigned char *tmpbuffer[NB_BUFFER];unsigned int tmpbytesused[NB_BUFFER];
}pic;int cam_fd;/*
Description.:Initalize V4L2 driver.
*/
int v4l2_init(void)
{int i;int ret = 0;// 1、Open camera deviceif((cam_fd = open(CAM_DEV,O_RDWR)) == -1){perror("ERROR opening V4L interface.");return -1;}// 2、Judge if the device is a camera device struct v4l2_capability cam_cap;if(ioctl(cam_fd,VIDIOC_QUERYCAP,&cam_cap) == -1){perror("Error opening device %s: unable to query device.");return -1;}if((cam_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {perror("ERROR video capture not supported.");return -1;}// 3、Setting output parameter.struct v4l2_format v4l2_fmt;v4l2_fmt.type = V4L2_CAP_VIDEO_CAPTURE;v4l2_fmt.fmt.pix.width = WIDTH;v4l2_fmt.fmt.pix.height = HEIGHT;v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;if (ioctl (cam_fd, VIDIOC_S_FMT, &v4l2_fmt) == -1) {   perror("ERROR camera VIDIOC_S_FMT Failed.");return -1;}// 4、Check whether the parameters are set successfully if (ioctl (cam_fd, VIDIOC_G_FMT, &v4l2_fmt) == -1) {perror("ERROR camera VIDIOC_G_FMT Failed.");return -1;}if (v4l2_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG){printf("Set VIDIOC_S_FMT sucessful\n");}// 5、Require buffer to store image datastruct v4l2_requestbuffers v4l2_req;v4l2_req.count = NB_BUFFER;v4l2_req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;v4l2_req.memory = V4L2_MEMORY_MMAP;if (ioctl (cam_fd, VIDIOC_REQBUFS, &v4l2_req) == -1) {perror("ERROR camera VIDIOC_REQBUFS Failed.");return -1;} // 6、Start memory mapstruct v4l2_buffer v4l2_buf;v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;v4l2_buf.memory = V4L2_MEMORY_MMAP;for(i = 0; i < NB_BUFFER; i++) {v4l2_buf.index = i;if(ioctl(cam_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0){perror("Unable to query buffer.");return -1;}pic.tmpbuffer[i] = (unsigned char*)mmap(NULL, v4l2_buf.length, PROT_READ, MAP_SHARED, cam_fd, v4l2_buf.m.offset);if(pic.tmpbuffer[i] == MAP_FAILED){perror("Unable to map buffer.");return -1;}if(ioctl(cam_fd, VIDIOC_QBUF, &v4l2_buf) < 0){perror("Unable to queue buffer.");return -1;}}//7、Open stream input int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if(ioctl(cam_fd, VIDIOC_STREAMON, &type) < 0){perror("Unable to start capture.");return -1;}return 0;
}/*
Description.:Get a jpeg image and save.
*/
int v4l2Grab(void)
{//8、Get a image struct v4l2_buffer buff;buff.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;buff.memory = V4L2_MEMORY_MMAP;if(ioctl(cam_fd, VIDIOC_DQBUF, &buff) < 0){printf("camera VIDIOC_DQBUF Failed.\n");usleep(1000*1000);return -1;}pic.tmpbytesused[buff.index] = buff.bytesused;printf("size : %d\n",pic.tmpbytesused[buff.index]);           //9、Save image./*int jpg_fd = open("1.jpeg",O_RDWR|O_CREAT,00700);if(jpg_fd == -1){printf("open ipg Failed!\n ");return -1;      }int writesize = write(jpg_fd, pic.tmpbuffer[buff.index], pic.tmpbytesused[buff.index]);printf("Write successfully size : %d\n",writesize);close(jpg_fd);*///10、Queue the buffers.if(ioctl(cam_fd, VIDIOC_QBUF, &buff) < 0){printf("camera VIDIOC_QBUF Failed.");usleep(1000*1000);return -1;}return 0;
}/*
Description.:Release resource
*/
int v4l2_close(void)
{// Remove mmap.int i;for(i=0; i<NB_BUFFER; i++)munmap(pic[0].tmpbuffer[i],pic[0].tmpbytesused[i]);close(cam_fd);return 0;
}/*
Description.:main
*/
int main(int argc, char* argv[])
{v4l2_init();while(1){        v4l2Grab();}v4l2_close();            return 0;
}

http://www.ppmy.cn/news/490061.html

相关文章

Linux开发板调用摄像头(V4L2编程,含YUYV解码RGB)

使用Linux的V4L2编程部分参考&#xff1a; Linux之V4L2基础编程 - emouse - 博客园 使用YUY2(YUV)与RGB之间相互转化参考&#xff1a; &#xff08;转&#xff09;RGB、YUY2、YUYV、YVYU、UYVY、AYUV格式详解 - 神一样的魔鬼 - 博客园 本文是基于Linux开发板的V4L2摄像头调用程…

全志V3s学习记录(13)OV2640的使用

文章目录 硬件分析一、修改设备树二、增加Linux驱动配置三、构建Buildroot文件系统使用I2c工具调试意外收获RAW看图软件 7yuv 测试 参考&#xff1a;https://blog.51cto.com/u_15294654/3111978 参考&#xff1a;https://blog.csdn.net/xiangkezhi167810/article/details/11225…

SpringBoot整合模板引擎Thymeleaf(4)

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 概述 在之前的教程中&#xff0c;我们介绍了Thymeleaf的基础知识。在此&#xff0c;以案例形式详细介绍Thymeleaf的基本使用。 项目结构 要点概述&#xff1a; 1、在st…

V4L2不支持一个数据输入端接多个输入线路

内核版本&#xff1a;4.4.162 &vi0 { status "okay"; port { #address-cells <1>; #size-cells <0>; vi_0_0: endpoint0 { reg <0>; remote-endpoint <&…

全志V3S 驱动OV2640 OV7725把图像显示到ST7789V LCD屏上

全志V3S 驱动OV2640 OV7725把图像显示到LCD屏上 文章目录 全志V3S 驱动OV2640 OV7725把图像显示到LCD屏上一、设备树添加摄像头驱动二、摄像头编译到内核三、编译重启查看启动log是否正常1.OV7725启动2.OV2640启动 四、C实现摄像头捕获图像显示到fb五、OV2640注意 一、设备树添…

Linux环境下使用V4L2+opencv以MJPEG格式读取USB摄像头并实时显示

转眼间&#xff0c;V4L2已经搞了很长时间&#xff0c;从最开始的一窍不通&#xff0c;到后来的渐渐熟悉&#xff0c;从最开始照猫画虎的使用YUYV格式之间转换&#xff0c;到后来使用MJPEG格式读取&#xff0c;中间颇有周折。趁任务完成间隙&#xff0c;来简单总结下V4L2的使用。…

【正点原子Linux连载】第二十章 V4L2摄像头应用编程-摘自【正点原子】I.MX6U嵌入式Linux C应用编程指南V1.1

1&#xff09;实验平台&#xff1a;正点原子阿尔法Linux开发板 2&#xff09;平台购买地址&#xff1a;https://item.taobao.com/item.htm?id603672744434 2&#xff09;全套实验源码手册视频下载地址&#xff1a;http://www.openedv.com/thread-300792-1-1.html 3&#xff09…

Linux的V4L2架构分析

V4L2全名为VideoFor Linux 2&#xff0c;它是针对Linux系统的视频设备处理架构。视频设备主要包括输入设备&#xff08;摄像头&#xff09;及输出设备&#xff08;显示设备&#xff09;。 一、Linux的V4L2架构介绍 V4L2的初衷是想为linux系统建立统一的视频类设备处理模型&…