c 摄像头利用v4l2直接生成avi视频(不利用ffmpeg)

这篇具有很好参考价值的文章主要介绍了c 摄像头利用v4l2直接生成avi视频(不利用ffmpeg)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

自定义avi结构头文件。现在不能实时显示摄像头画面,准备参照fim(终端中显示图片),直接对显示framebuffer操作,显示视频。不用qt等。

生成的视频根据机子的性能不同,诂计要手动调一下生成视频的帧率。

播放: $ aplay  musicdemo.wmv

录音: $ arecord -c 2 -r 44100 -f S16_LE musicdemo.wmv

调节音量大小: $ alsamixer 

deepin安装 alsa-lib

sudo apt-get install libasound2-dev   

main.c


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>
#include "Avi.h"

 

int main(void){
	int fd = open("/dev/video0", O_RDWR);
	if(fd < 0)
	{
		perror("打开设备失败");
		return -1;
	}
	struct v4l2_format vfmt;
	vfmt.type=1;
	vfmt.fmt.pix.width=1680;         
	vfmt.fmt.pix.height=1080;
	vfmt.fmt.pix.pixelformat=V4L2_PIX_FMT_MJPEG; 
	int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);
	if(ret < 0)
	{
		perror("设置格式失败");
	}
	
	struct v4l2_requestbuffers reqbuffer;
	reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	reqbuffer.count = 1; 
	reqbuffer.memory = V4L2_MEMORY_MMAP ;
	ret  = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);
	if(ret < 0)
	{
		perror("申请队列空间失败");
	}
	
	struct v4l2_buffer mapbuffer;
	unsigned char *mptr;
	unsigned int  size;
	mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	mapbuffer.index = 0;
	
	ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//查询缓冲区状态
	if(ret < 0)
	{
		perror("查询内核空间队列失败");
	}
	
	int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ret = ioctl(fd, VIDIOC_STREAMON, &type);     //启动流
	if(ret < 0)
	{
		perror("开启失败");
	}
	
	mptr= (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE, 
		MAP_SHARED, fd,0);       //设备映射到缓冲区内存
	size=mapbuffer.length;
	
	ret  = ioctl(fd, VIDIOC_QBUF, &mapbuffer);    //把缓冲区数据放入读队列中
	if(ret < 0)                                   
	{
		perror("放回失败");
	}
//---------------------------------------------------------------------------
    FILE *file=avi_ks();
	
	while(nframes<100){
	ret = ioctl(fd, VIDIOC_DQBUF, &mapbuffer);       //读当前队列缓冲区的数据
	if(ret < 0)
	{
		perror("提取数据失败");
	}
	int size=1280*720;
	unsigned char tmp[4] = {'0', '0', 'd', 'c'};  //00dc = 压缩的视频数据
	fwrite(tmp, 4, 1, file);    //写入是否是压缩的视频数据信息
	fwrite(&size, 4, 1, file);   //写入4字节对齐后的JPEG图像大小
	fwrite(mptr,size, 1, file); //写入真正的JPEG数据
		
	ret  = ioctl(fd, VIDIOC_QBUF, &mapbuffer);    //把缓冲区数据放入读队列中
	if(ret < 0)                                   
	{
		perror("放回失败");
	}
	 nframes++;           
     totalsize++;         

	}
	
//---------------------------------------------------------
	ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
	
	avi_end(file);
	
	munmap(mptr, size);
	
	close(fd);
	
	return 0;
}

avi.c


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "Avi.h"




FILE * avi_ks(void){	

	FILE *fp= fopen("sample.avi","wb");

	fseek(fp,sizeof(HEAD),SEEK_SET);

	return fp;
}
	
	//--------------------------------------------------------
 int avi_add(FILE*fp,char *data,int size){
	
			unsigned char tmp[4] = {'0', '0', 'd', 'c'};  //00dc = 压缩的视频数据
			fwrite(tmp, 4, 1, fp);    //写入是否是压缩的视频数据信息
			fwrite(&size, 4, 1, fp);   //写入4字节对齐后的JPEG图像大小
			fwrite(data,size, 1, fp); //写入真正的JPEG数据
			return 0;
	}
 
 //----------------------------------------------------------------------------------
 int avi_end(FILE *f_file){
	 
	int width=1280;
	int height=720;
	
	
	typedef  struct hdrl AVI_HDRL_LIST;
	typedef  struct movi AVI_LIST_HEAD;
	typedef  struct avih AVI_AVIH_CHUNK;
	typedef  struct strl AVI_STRL_LIST;
	typedef  struct strh  AVI_STRH_CHUNK;
	typedef  struct strf  AVI_STRF_CHUNK;
	typedef  struct  avi   AVI_HEAD;
	
	AVI_HEAD  avi_head={ 
		
		{
			{'R', 'I', 'F', 'F'},
			4 + sizeof(AVI_HDRL_LIST) + sizeof(AVI_LIST_HEAD) +nframes * 8 + totalsize,
			{'A', 'V', 'I', ' '}
		},
		
		{
			{'L', 'I', 'S', 'T'},
			sizeof(AVI_HDRL_LIST) - 8,
			{'h', 'd', 'r', 'l'},
			{
				{'a', 'v', 'i', 'h'},
				sizeof(AVI_AVIH_CHUNK) - 8,
				1000000, 25000, 0, 0,nframes, 0, 1, 1000000, width, height,
				{0, 0, 0, 0}
			},
			{
				{'L', 'I', 'S', 'T'},
				sizeof(AVI_STRL_LIST) - 8,
				{'s', 't', 'r', 'l'},
				{
					{'s', 't', 'r', 'h'},
					sizeof(AVI_STRH_CHUNK) - 8,
					{'v', 'i', 'd', 's'},
					{'J', 'P', 'E', 'G'},
					0, 0, 0, 0, 1, 15, 0, nframes, 100000, 0xFFFFFF, 0,
					{0, 0, width, height}
				},
				{
					{'s', 't', 'r', 'f'},
					sizeof(AVI_STRF_CHUNK) - 8,
					sizeof(AVI_STRF_CHUNK) - 8,
					width, height, 1, 24,
					{'J', 'P', 'E', 'G'},
					width * height * 3, 0, 0, 0, 0
				}
			}
			
		},
		
		{
			{'L', 'I', 'S', 'T'},
			4 + nframes * 8 + totalsize,
			{'m', 'o', 'v', 'i'}
		}
	};
	
	
	fseek(f_file, 0, SEEK_SET);
	
	fwrite(&avi_head,sizeof(HEAD),1,f_file);
	
	fclose(f_file);
	printf("end\n");
 }
 


avi.h文章来源地址https://www.toymoban.com/news/detail-721703.html


#ifndef AVI_H
#define AVI_H
#include <stdio.h>
static int nframes;           //总帧数
static int totalsize; 
FILE * avi_ks(void);
int avi_add(FILE*fp,char *data,int size);
int avi_end(FILE *f_file);

struct avi{
	struct riff{
		unsigned char id[4];
		unsigned int size;
		unsigned char type[4];
	}r1;
	
	
	struct hdrl{
		unsigned char id[4];    //块ID,固定为LIST
		unsigned int size;      //块大小,等于struct avi_hdrl_list去掉id和size的大小
		unsigned char type[4];  //块类型,固定为hdrl
		
		struct avih{
			unsigned char id[4];            //块ID,固定为avih
			unsigned int size;              //块大小,等于struct avi_avih_chunk去掉id和size的大小
			unsigned int us_per_frame;      //视频帧间隔时间(以微秒为单位)
			unsigned int max_bytes_per_sec; //AVI文件的最大数据率
			unsigned int padding;           //设为0即可
			unsigned int flags;             //AVI文件全局属性,如是否含有索引块、音视频数据是否交叉存储等
			unsigned int total_frames;      //总帧数
			unsigned int init_frames;       //为交互格式指定初始帧数(非交互格式应该指定为0)
			unsigned int streams;           //文件包含的流的个数,仅有视频流时为1
			unsigned int suggest_buff_size; //指定读取本文件建议使用的缓冲区大小,通常为存储一桢图像                                            //以及同步声音所需的数据之和,不指定时设为0
			unsigned int width;             //视频主窗口宽度(单位:像素)
			unsigned int height;            //视频主窗口高度(单位:像素)
			unsigned int reserved[4];       //保留段,设为0即可
		}a1;
		
		struct   strl{
			unsigned char id[4];    //块ID,固定为LIST
			unsigned int size;      //块大小,等于struct avi_strl_list去掉id和size的大小
			unsigned char type[4];  //块类型,固定为strl
			
			struct strh{
				unsigned char id[4];            //块ID,固定为strh
				unsigned int size;              //块大小,等于struct avi_strh_chunk去掉id和size的大小
				unsigned char stream_type[4];   //流的类型,vids表示视频流,auds表示音频流
				unsigned char codec[4];         //指定处理这个流需要的解码器,如JPEG
				unsigned int flags;             //标记,如是否允许这个流输出、调色板是否变化等,一般设为0即可
				unsigned short priority;        //流的优先级,视频流设为0即可
				unsigned short language;        //音频语言代号,视频流设为0即可
				unsigned int init_frames;       //为交互格式指定初始帧数(非交互格式应该指定为0)
				unsigned int scale;             //
				unsigned int rate;              //对于视频流,rate / scale = 帧率fps
				unsigned int start;             //对于视频流,设为0即可
				unsigned int length;            //对于视频流,length即总帧数
				unsigned int suggest_buff_size; //读取这个流数据建议使用的缓冲区大小
				unsigned int quality;           //流数据的质量指标
				unsigned int sample_size;       //音频采样大小,视频流设为0即可
				struct rcFrame{                 //这个流在视频主窗口中的显示位置,设为{0,0,width,height}即可
					
					short left;
					short top;
					short right;
					short bottom;
				} AVI_RECT_FRAME;      
			}s1;
			
			struct strf{
				unsigned char id[4];             //块ID,固定为strf
				unsigned int size;               //块大小,等于struct avi_strf_chunk去掉id和size的大小
				unsigned int size1;              //size1含义和值同size一样
				unsigned int width;              //视频主窗口宽度(单位:像素)
				unsigned int height;             //视频主窗口高度(单位:像素)
				unsigned short planes;           //始终为1
				unsigned short bitcount;         //每个像素占的位数,只能是1、4、8、16、24和32中的一个
				unsigned char compression[4];    //视频流编码格式,如JPEG、MJPG等
				unsigned int image_size;         //视频图像大小,等于width * height * bitcount / 8
				unsigned int x_pixels_per_meter; //显示设备的水平分辨率,设为0即可
				unsigned int y_pixels_per_meter; //显示设备的垂直分辨率,设为0即可
				unsigned int num_colors;         //含义不清楚,设为0即可
				unsigned int imp_colors;         //含义不清楚,设为0即可
			}q1;
			
		}w1;
		
	}a1;
	
	struct movi{
		unsigned char id[4];
		unsigned int size;
		unsigned char type[4];
	}movi1;
	
}HEAD;

#endif

到了这里,关于c 摄像头利用v4l2直接生成avi视频(不利用ffmpeg)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Ubuntu下python-opencv无法打开摄像头,open VIDEOIO(V4L2:/dev/video0): can‘t open camera by index

    我们在ubuntu下使用opencv获取摄像头画面是,报错 open VIDEOIO(V4L2:/dev/video0): can‘t open camera by index 然后观察虚拟机桌面的右下角,如果出现摄像头有小绿点表示连接成功 然后我们来测试一下,摄像头的画面 ####### 这是摄像头传输回来的画面

    2024年02月16日
    浏览(42)
  • RK3568 android11 移植 v4l2loopback 虚拟摄像头

    v4l2loopback是一个Linux内核模块,它允许用户创建虚拟视频设备。这种虚拟视频设备可以用于各种用途,例如将实际摄像头的视频流复制到虚拟设备上,或者用于视频流的处理和分析等。v4l2loopback的主要作用是 创建一个虚拟的Video4Linux2设备,它可以接收来自其他应用程序的视频

    2024年01月19日
    浏览(64)
  • V4L2常用调试命令

    这篇文章简单记录一下RK平台基于V4L2框架camera调试过程中常用的一些命令: (1)查看拓扑结构:查看media0的pipeline (2)抓数据流命令: 对video0节点,设置格式为NV12,分辨率为1920x1080,不裁剪,4个buf轮转,--verbose的作用是刷出帧率。 (3)抓图命令: 类似上面的,将图像保

    2024年02月03日
    浏览(46)
  • Linux之V4L2驱动框架

    目录 一、V4L2简介 二、V4L2操作流程  1.打开摄像头 2.查询设备的属性/能力/功能 3.获取摄像头支持的格式 4.设置摄像头的采集通道 5.设置/获取摄像头的采集格式和参数 6.申请帧缓冲、内存映射、入队 (1)申请帧缓冲 (2)内存映射 (3)入队 7.开启视频采集 8.读取数据、对数

    2024年02月08日
    浏览(38)
  • V4L2+QT+USB摄像头实时显示视频(Arm,Linux,window均适用)

    笔者自从学习了Framebuffer编程和V4L2编程之后,就想实现在LCD屏上显示实时视频 笔者学习过正点I.MX6U Linux C编程中的相关内容,然而原子的例程是针对OV5640摄像头写的,像素格式是RGB 然而USB摄像头大多支持MJPEG或者YUYV格式,如果要在屏幕上显示需要进行格式转换,而 转换像素

    2023年04月08日
    浏览(44)
  • 项目之利用 V4L2应用程序框架 进行视频录制

    目录 知识储备: 视频采集方式: 处理采集数据: 相关结构体: 对于设备的操作步骤:         V4L2较V4L有较大的改动,并已成为 2.6 的标准接口,函盖 videodvbFM... ,多数驱动都在向 V4l2 迁移。更好地了解 V4L2 先从应用入手,然后再深入到内核中结合物理设备/接口的规范实现

    2023年04月09日
    浏览(41)
  • 汽车IVI中控开发入门及进阶(十二):V4L2视频

    前言     IVI,In-Vehicle Infotainment,智能座舱信息娱乐系统,或称车载信息娱乐系统, 汽车中控也被称为车机、车载多媒体、车载娱乐等, 它是智能座舱的重要组成部分。IVI 采用车载专用中央处理器,基于车身总线系统和联网服务提供车载综合信息处理功能,包括音频播放、

    2024年02月04日
    浏览(48)
  • 【C++】开源:Linux端V4L2视频设备库

    😏 ★,° :.☆( ̄▽ ̄)/$: .°★ 😏 这篇文章主要介绍Linux端V4L2视频设备库。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下次更新不迷路🥞 Video4Linux2( V4L2 )是一个用于Linux操作系统的视频设备驱动框

    2024年02月11日
    浏览(34)
  • 内存不足V4L2 申请DMC缓存报错问题

    当内存不足时,V4L2可能存在申请DMA缓存报错,如下日志:

    2024年02月12日
    浏览(37)
  • RK3568平台开发系列讲解(驱动基础篇)V4L2 用户空间 API 说明

    🚀返回专栏总目录 沉淀、分享、成长,让自己和他人都能有所收获!😄 📢设备驱动的主要目的是控制和利用底层硬件,同时向用户展示功能。 这些用户可以是在用户空间或其他内核驱动中运行的应用。 本篇我们将学习如何利用内核公开的 V4L2 设备功能。 我们将从描述和

    2023年04月25日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包