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

编程入门 行业动态 更新时间:2024-10-09 08:29:15

c 实用化的摄像头生成avi视频程序(加入<a href=https://www.elefans.com/category/jswz/34/1764196.html style=精确的时间控制)"/>

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

 

 

 

 

 

更多推荐

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

本文发布于:2023-11-15 02:14:44,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1591935.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:精确   摄像头   时间   程序   视频

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!