c 实用化的摄像头生成avi视频程序(加入精确的时间控制)

I时间控制是指:生成了n张图片帧用了多少时间m。帧率等于n/m。对应于头文件,m等于scale,  n等于rate.为了精确,采用微秒计时。

I此程序生成的视频远好于ffmpeg,可能是此程序没有压缩数据原因吧。

现在的帧率不高,是因为只用了一个摄像头缓存区。

avi 头文件


#ifndef AVI_H
#define AVI_H
#include <stdio.h>//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];}ri1;struct hdrl{unsigned char id[4];    //块ID,固定为LISTunsigned int size;      //块大小,等于struct avi_hdrl_list去掉id和size的大小unsigned char type[4];  //块类型,固定为hdrlstruct avih{unsigned char id[4];            //块ID,固定为avihunsigned 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;           //文件包含的流的个数,仅有视频流时为1unsigned int suggest_buff_size; //指定读取本文件建议使用的缓冲区大小,通常为存储一桢图像                                            //以及同步声音所需的数据之和,不指定时设为0unsigned int width;             //视频主窗口宽度(单位:像素)unsigned int height;            //视频主窗口高度(单位:像素)unsigned int reserved[4];       //保留段,设为0即可}ah1;struct   strl{unsigned char id[4];    //块ID,固定为LISTunsigned int size;      //块大小,等于struct avi_strl_list去掉id和size的大小unsigned char type[4];  //块类型,固定为strlstruct strh{unsigned char id[4];            //块ID,固定为strhunsigned int size;              //块大小,等于struct avi_strh_chunk去掉id和size的大小unsigned char stream_type[4];   //流的类型,vids表示视频流,auds表示音频流unsigned char codec[4];         //指定处理这个流需要的解码器,如JPEGunsigned int flags;             //标记,如是否允许这个流输出、调色板是否变化等,一般设为0即可unsigned short priority;        //流的优先级,视频流设为0即可unsigned short language;        //音频语言代号,视频流设为0即可unsigned int init_frames;       //为交互格式指定初始帧数(非交互格式应该指定为0)unsigned int scale;             //unsigned int rate;              //对于视频流,rate / scale = 帧率fpsunsigned 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;      }sh1;struct strf{unsigned char id[4];             //块ID,固定为strfunsigned int size;               //块大小,等于struct avi_strf_chunk去掉id和size的大小unsigned int size1;              //size1含义和值同size一样unsigned int width;              //视频主窗口宽度(单位:像素)unsigned int height;             //视频主窗口高度(单位:像素)unsigned short planes;           //始终为1unsigned short bitcount;         //每个像素占的位数,只能是1、4、8、16、24和32中的一个unsigned char compression[4];    //视频流编码格式,如JPEG、MJPG等unsigned int image_size;         //视频图像大小,等于width * height * bitcount / 8unsigned int x_pixels_per_meter; //显示设备的水平分辨率,设为0即可unsigned int y_pixels_per_meter; //显示设备的垂直分辨率,设为0即可unsigned int num_colors;         //含义不清楚,设为0即可unsigned int imp_colors;         //含义不清楚,设为0即可}sf1;}sl1;}hd1;struct movi{unsigned char id[4];unsigned int size;unsigned char type[4];}movi1;}HEAD;#endif

主程序


#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"
#include <sys/time.h>#define wid  1280            //摄像头图像宽度
#define hei  720             //图像高度
#define bitlen 24            //图像采样宽度
#define perframe  30          //先预估一帧率,可以为摄像头最大帧率,实际使用时的帧率小于次值
#define   jhframe  30         //准备要录像的图片帧数,控制录像的时间长度static int nframes=0;           //总帧数
static int totalsize=0;         //总字节数FILE * avi_ks(void) {FILE *fp = fopen("sample.avi", "w+b");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 = wid;int height = hei;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/perframe,width*height*bitlen*perframe/8, 0, 0, nframes,0, 1,width*height*bitlen/8, 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,         //475020000,        //200000, nframes,width*height*bitlen*perframe/8,10000, 0,{0, 0, width, height}},{{'s', 't', 'r', 'f'},sizeof(AVI_STRF_CHUNK) - 8,sizeof(AVI_STRF_CHUNK) - 8,width, height, 1,bitlen,{'J', 'P', 'E', 'G'},width * height *bitlen/8, 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);return 0;
}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=wid;         vfmt.fmt.pix.height=hei;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();struct timeval start,end;  gettimeofday(&start, NULL );         //微秒记时开始while(nframes<jhframe){ret = ioctl(fd, VIDIOC_DQBUF, &mapbuffer);       //读当前队列缓冲区的数据if(ret < 0){perror("提取数据失败");}int size=wid*hei*bitlen/8;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++;         }static float timeuse1=0;gettimeofday(&end, NULL );       //记时结束timeuse1 =1000*(1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec); int timeuse=(int)(timeuse1/1000000);  //转换为豪秒//---------------------------------------------------------ret = ioctl(fd, VIDIOC_STREAMOFF, &type);avi_end(file);int scale=timeuse;  int rate=nframes*1000;         //重写实际帧率=rate/scale ,乘1000是timeuse 为毫秒,转换为秒fseek(file,128,SEEK_SET);      //128 为scale 在文件中的字节位数(偏移)fwrite(&scale,4,1,file);fwrite(&rate,4,1,file);        //rate 为128+4 位fclose(file);munmap(mptr, size);/*	FILE *ss=fopen("sample.avi","rb");    //检验scale ,rate 新值fseek(ss,0,SEEK_END);int len=ftell(ss);int ff=fileno(ss);char *tf=mmap(NULL,len,PROT_READ,MAP_SHARED,ff,0);memcpy(&HEAD,&tf[0],sizeof(HEAD));printf("scale:%d\n",HEAD.hd1.sl1.sh1.scale);printf("rate:%d\n",HEAD.hd1.sl1.sh1.rate);printf("end\n");
*/	close(fd);return 0;
}

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/141324.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java之“数字困境”:资产管理项目中的Bug追踪与启示

目录 1 前言2 问题的发现3 调试的开始4 深入调试5 调试心得与反思6 结语 1 前言 在程序员的日常工作中&#xff0c;我们时常面对各种令人头疼的问题&#xff0c;其中最令人崩溃的瞬间之一&#xff0c;就是当我们花费大量时间追踪一个看似复杂的bug&#xff0c;最终发现问题的根…

C# PDF转HTML字符串

需要nuget安装Aspose.PDF插件&#xff0c;本文使用23.10.0版本 一、获取PDF文件&#xff0c;保存到某个路径&#xff1b;再读取返回字符串。 //html文件保存路径 string filePath dirPath "xxx.html"; if (!File.Exists(filePath)) {//获取pdf文件流Byte[] pdfBy…

windows安装composer并更换国内镜像

第一步、官网下载 下载地址 Composer安装https://getcomposer.org/Composer-Setup.exe第二步、双击安装即可 第三步选择 php安装路径并配置path 第四步、 composer -v查看安装是否成功&#xff0c;出现成功界面 第五步、查看镜像地址并更换&#xff08;composer国内可能较慢…

达梦数据库安装

一、官网参考文档 达梦数据库官网&#xff1a;https://www.dameng.com/ &#xff0c;参考文档如下&#xff1a; 最后的文档地址为&#xff1a;Docker安装 | 达梦技术文档 二、dcoker安装 docker基本按照官网来就行&#xff0c;点击相应的链接下载镜像包。 复制到linux中&#x…

Linux命令——ssh

Linux命令——ssh 背景 SSH&#xff08;Secure Shell 的缩写&#xff09;是一种网络协议&#xff0c;用于加密两台计算机之间的通信&#xff0c;并且支持各种身份验证机制。 历史上&#xff0c;网络主机之间的通信是不加密的&#xff0c;属于明文通信。这使得通信很不安全&a…

万界星空科技智能管理系统低代码平台

低代码平台正成为企业数字化基础设施的重要一环&#xff0c;越来越多的企业为了可持续的数字化建设&#xff0c;开始启用低代码平台&#xff0c;其选型除了平台易用性、应用搭建能力外&#xff0c;也关注与第三方平台的集成性&#xff0c;及厂商对行业knowhow的积累、品牌口碑及…

LeetCode(9)跳跃游戏【数组/字符串】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 55. 跳跃游戏 1.题目 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回…

解决服务器中的mysql连接不上Navicat的问题脚本

shell标本&#xff0c;快速解决服务器中的mysql连接不上Navicat的问题 在Linux服务器开发中&#xff0c;mysql的配置文件一般是只允许本地连接 所以想用Navicat进行连接&#xff0c;就需要修改配置和mysql中用户访问表的权限 为了方便&#xff0c;写成了shell脚本 #!/bin/bas…

飞天使-django概念之urls

urls 容易搞混的概念&#xff0c;域名&#xff0c;主机名&#xff0c;路由 网站模块多主机应用 不同模块解析不同的服务器ip地址 网页模块多路径应用 urlpatterns [ path(‘admin/’, admin.site.urls), path(‘’, app01views.index), path(‘movie/’, app01views.movi…

ffmpeg命令行处理视频,学习记录

ffmpeg命令行处理视频 截取视频前5s ffmpeg -ss 00:00:00 -t 00:00:05 -i .\public\uploads\20231109\116a292eccf8315f65d7166e794d1730.mp4 .\public\uploads\20231109\116a292eccf8315f65d7166e794d1731.mp4两视频合并为1个 ffmpeg -i F:\xuejiao\code\cms.openlai.com\p…

5 新的关键字

动态内存分配 回想C语言中&#xff0c;动态内存是怎么分配的&#xff1f;通过C库里面的malloc free去进行动态内存分配。 C通过new关键字进行动态内存申请&#xff0c;动态内存申请是基于类型进行的。 delete 关键字用于内存释放。 //变量申请 type* pointer new type; dele…

友元的三种实现

友元的三种实现 全局函数做友元类做友元成员函数做友元 #include <iostream> #include <string> using namespace std;//友元的三种实现 // //* 全局函数做友元 //* 类做友元 //* 成员函数做友元class Building {//告诉编译器 goodGay全局函数 是 Building类的好…

[Socket]Unix socket 运行权限问题

Unix socket 运行权限问题 hongxi.zhu 2023-11-13 问题&#xff1a;socket只能在当前源码目录运行&#xff0c;换个路径或者换个机子运行&#xff0c;如果是服务端&#xff0c;启动则会出现无法bind, 客户端则会出现无法connect 原因&#xff1a;unix socket是基于文件的fd方式…

Mistral 7B 比Llama 2更好的开源大模型 (一)

Mistral 7B 简介 Mistral 7B Mistral 7B 是一个 7.3B 参数模型: 在所有基准测试中优于 Llama 2 13B在许多基准测试中优于 Llama 1 34B接近 CodeLlama 7B 的代码性能,同时保持擅长英语任务使用分组查询注意力 (GQA) 加快推理速度使用滑动窗口注意力 (SWA) 以更低的成本处…

K8S集群etcd 某个节点数据不一致如何修复 —— 筑梦之路

背景说明 二进制方式安装的k8s集群&#xff0c;etcd集群有3个节点&#xff0c;某天有一台机器hang住了&#xff0c;无法远程ssh登陆&#xff0c;于是被管理员直接重启了&#xff0c;重启后发现k8s集群删除一个deployment应用&#xff0c;多次刷新一会有&#xff0c;一会没有&am…

[Android]新建项目使用AppCompatActivity后运行闪退

报错 日志&#xff1a; Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity. FATAL EXCEPTION: main Process: com.example.gatestdemol, PID: 26071 java.lang.RuntimeException: Unable to start a…

DefaultListableBeanFactory

DefaultListableBeanFactory 是一个完整的、功能成熟的 IoC 容器&#xff0c;如果你的需求很简单&#xff0c;甚至可以直接使用 DefaultListableBeanFactory&#xff0c;如果你的需求比较复杂&#xff0c;那么通过扩展 DefaultListableBeanFactory 的功能也可以达到&#xff0c…

Netty实现通信框架

一、LengthFieldBasedFrameDecoder的参数解释 1、LengthFieldBasedFrameDecoder的构造方法参数 看下最多参数的构造方法 /*** Creates a new instance.** param byteOrder* the {link ByteOrder} of the length field* param maxFrameLength* the maximum len…

Redis快速入门(基础篇)

简介&#xff1a; 是一个高性能的 key-value数据库。 存在内存中 与其他 key-value 缓存产品有以下三个特点&#xff1a; Redis支持数据的持久化&#xff0c;可以将内存中的数据保持在磁盘中&#xff0c;重启的时候可以再次加载进行使用。 Redis不仅仅支持简单的key-value类…

nodejs+vue+python+PHP+微信小程序-安卓- 电影在线订票系统的设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…