欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言調(diào)用攝像頭生成avi視頻程序

 更新時(shí)間:2023年11月14日 14:11:19   作者:樂山勁松  
這篇文章主要為大家詳細(xì)介紹了C語言如何調(diào)用攝像頭生成avi視頻程序,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下

時(shí)間控制是指:生成了n張圖片幀用了多少時(shí)間m。幀率等于n/m。對應(yīng)于頭文件,m等于scale,  n等于rate.為了精確,采用微秒計(jì)時(shí)。

此程序生成的視頻遠(yuǎn)好于ffmpeg,可能是此程序沒有壓縮數(shù)據(jù)原因吧。

現(xiàn)在的幀率不高,是因?yàn)橹挥昧艘粋€(gè)攝像頭緩存區(qū)。

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,固定為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;      //視頻幀間隔時(shí)間(以微秒為單位)
			unsigned int max_bytes_per_sec; //AVI文件的最大數(shù)據(jù)率
			unsigned int padding;           //設(shè)為0即可
			unsigned int flags;             //AVI文件全局屬性,如是否含有索引塊、音視頻數(shù)據(jù)是否交叉存儲(chǔ)等
			unsigned int total_frames;      //總幀數(shù)
			unsigned int init_frames;       //為交互格式指定初始幀數(shù)(非交互格式應(yīng)該指定為0)
			unsigned int streams;           //文件包含的流的個(gè)數(shù),僅有視頻流時(shí)為1
			unsigned int suggest_buff_size; //指定讀取本文件建議使用的緩沖區(qū)大小,通常為存儲(chǔ)一楨圖像                                            //以及同步聲音所需的數(shù)據(jù)之和,不指定時(shí)設(shè)為0
			unsigned int width;             //視頻主窗口寬度(單位:像素)
			unsigned int height;            //視頻主窗口高度(單位:像素)
			unsigned int reserved[4];       //保留段,設(shè)為0即可
		}ah1;
		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];         //指定處理這個(gè)流需要的解碼器,如JPEG
				unsigned int flags;             //標(biāo)記,如是否允許這個(gè)流輸出、調(diào)色板是否變化等,一般設(shè)為0即可
				unsigned short priority;        //流的優(yōu)先級,視頻流設(shè)為0即可
				unsigned short language;        //音頻語言代號,視頻流設(shè)為0即可
				unsigned int init_frames;       //為交互格式指定初始幀數(shù)(非交互格式應(yīng)該指定為0)
				unsigned int scale;             //
				unsigned int rate;              //對于視頻流,rate / scale = 幀率fps
				unsigned int start;             //對于視頻流,設(shè)為0即可
				unsigned int length;            //對于視頻流,length即總幀數(shù)
				unsigned int suggest_buff_size; //讀取這個(gè)流數(shù)據(jù)建議使用的緩沖區(qū)大小
				unsigned int quality;           //流數(shù)據(jù)的質(zhì)量指標(biāo)
				unsigned int sample_size;       //音頻采樣大小,視頻流設(shè)為0即可
				struct rcFrame{                 //這個(gè)流在視頻主窗口中的顯示位置,設(shè)為{0,0,width,height}即可
					short left;
					short top;
					short right;
					short bottom;
				} AVI_RECT_FRAME;      
			}sh1;
			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;         //每個(gè)像素占的位數(shù),只能是1、4、8、16、24和32中的一個(gè)
				unsigned char compression[4];    //視頻流編碼格式,如JPEG、MJPG等
				unsigned int image_size;         //視頻圖像大小,等于width * height * bitcount / 8
				unsigned int x_pixels_per_meter; //顯示設(shè)備的水平分辨率,設(shè)為0即可
				unsigned int y_pixels_per_meter; //顯示設(shè)備的垂直分辨率,設(shè)為0即可
				unsigned int num_colors;         //含義不清楚,設(shè)為0即可
				unsigned int imp_colors;         //含義不清楚,設(shè)為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          //先預(yù)估一幀率,可以為攝像頭最大幀率,實(shí)際使用時(shí)的幀率小于次值
#define   jhframe  30         //準(zhǔn)備要錄像的圖片幀數(shù),控制錄像的時(shí)間長度
static int nframes=0;           //總幀數(shù)
static int totalsize=0;         //總字節(jié)數(shù)
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 = 壓縮的視頻數(shù)據(jù)
	fwrite(tmp, 4, 1, fp);    //寫入是否是壓縮的視頻數(shù)據(jù)信息
	fwrite(&size, 4, 1, fp);   //寫入4字節(jié)對齊后的JPEG圖像大小
	fwrite(data, size, 1, fp); //寫入真正的JPEG數(shù)據(jù)
	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,         //4750
					20000,        //20000
					0, 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("打開設(shè)備失敗");
		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("設(shè)置格式失敗");
	}
	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("申請隊(duì)列空間失敗");
	}
	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);//查詢緩沖區(qū)狀態(tài)
	if(ret < 0)
	{
		perror("查詢內(nèi)核空間隊(duì)列失敗");
	}
	int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ret = ioctl(fd, VIDIOC_STREAMON, &type);     //啟動(dòng)流
	if(ret < 0)
	{
		perror("開啟失敗");
	}
	mptr= (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE, 
		MAP_SHARED, fd,0);       //設(shè)備映射到緩沖區(qū)內(nèi)存
	size=mapbuffer.length;
	ret  = ioctl(fd, VIDIOC_QBUF, &mapbuffer);    //把緩沖區(qū)數(shù)據(jù)放入讀隊(duì)列中
	if(ret < 0)                                   
	{
		perror("放回失敗");
	}
//---------------------------------------------------------------------------
	FILE *file=avi_ks();
	struct timeval start,end;  
	gettimeofday(&start, NULL );         //微秒記時(shí)開始
	while(nframes<jhframe){
		ret = ioctl(fd, VIDIOC_DQBUF, &mapbuffer);       //讀當(dāng)前隊(duì)列緩沖區(qū)的數(shù)據(jù)
		if(ret < 0)
		{
			perror("提取數(shù)據(jù)失敗");
		}
		int size=wid*hei*bitlen/8;
		unsigned char tmp[4] = {'0', '0', 'd', 'c'};  //00dc = 壓縮的視頻數(shù)據(jù)
		fwrite(tmp, 4, 1, file);    //寫入是否是壓縮的視頻數(shù)據(jù)信息
		fwrite(&size, 4, 1, file);   //寫入4字節(jié)對齊后的JPEG圖像大小
		fwrite(mptr,size, 1, file); //寫入真正的JPEG數(shù)據(jù)
		ret  = ioctl(fd, VIDIOC_QBUF, &mapbuffer);    //把緩沖區(qū)數(shù)據(jù)放入讀隊(duì)列中
		if(ret < 0)                                   
		{
			perror("放回失敗");
		}
		nframes++;           
		totalsize++;         
	}
	static float timeuse1=0;
	gettimeofday(&end, NULL );       //記時(shí)結(jié)束
    timeuse1 =1000*(1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec); 
	int timeuse=(int)(timeuse1/1000000);  //轉(zhuǎn)換為豪秒
//---------------------------------------------------------
	ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
	avi_end(file);
	int scale=timeuse;  
    int rate=nframes*1000;         //重寫實(shí)際幀率=rate/scale ,乘1000是timeuse 為毫秒,轉(zhuǎn)換為秒
	fseek(file,128,SEEK_SET);      //128 為scale 在文件中的字節(jié)位數(shù)(偏移)
	fwrite(&scale,4,1,file);
	fwrite(&rate,4,1,file);        //rate 為128+4 位
	fclose(file);
	munmap(mptr, size);
/*	FILE *ss=fopen("sample.avi","rb");    //檢驗(yàn)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;
}

到此這篇關(guān)于C語言調(diào)用攝像頭生成avi視頻程序的文章就介紹到這了,更多相關(guān)C語言生成avi視頻內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言 全局變量和局部變量詳解及實(shí)例

    C語言 全局變量和局部變量詳解及實(shí)例

    這篇文章主要介紹了C語言 全局變量和局部變量詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • C++報(bào)錯(cuò):Segmentation Fault的解決方案

    C++報(bào)錯(cuò):Segmentation Fault的解決方案

    段錯(cuò)誤(Segmentation Fault)是 C++ 編程中常見且令人頭疼的錯(cuò)誤之一,段錯(cuò)誤通常發(fā)生在程序試圖訪問未被允許的內(nèi)存區(qū)域時(shí),導(dǎo)致程序崩潰,本文將深入探討段錯(cuò)誤的產(chǎn)生原因、檢測方法及其預(yù)防和解決方案,需要的朋友可以參考下
    2024-07-07
  • C++中友元類和嵌套類使用詳解

    C++中友元類和嵌套類使用詳解

    友元是一種允許非類成員函數(shù)訪問類的非公有成員的一種機(jī)制??梢园岩粋€(gè)函數(shù)指定為類的友元,也可以把整個(gè)類指定為另一個(gè)類的友元,所謂嵌套類,就是在類中聲明的類。如下代碼中,類Inner就是一個(gè)嵌套類,類Outer是外圍類
    2022-08-08
  • Dijkstra最短路徑算法實(shí)現(xiàn)代碼

    Dijkstra最短路徑算法實(shí)現(xiàn)代碼

    這篇文章主要介紹了Dijkstra最短路徑算法實(shí)現(xiàn)代碼,有需要的朋友可以參考一下
    2013-12-12
  • QT線程QThread的使用介紹

    QT線程QThread的使用介紹

    在進(jìn)行桌面應(yīng)用程序開發(fā)的時(shí)候,假設(shè)程序在某些情況要處理復(fù)雜邏輯, 如果一個(gè)線程去處理,就會(huì)導(dǎo)致窗口卡頓,無法處理用戶操作。這就需要使用多線程,其中一個(gè)線程處理窗口事件,其他線程進(jìn)行邏輯運(yùn)算,多個(gè)線程各司其職,不僅可以提高用戶體驗(yàn)還可以提升程序的執(zhí)行效率
    2022-09-09
  • C/C++數(shù)字與字符串互相轉(zhuǎn)換的實(shí)現(xiàn)示例

    C/C++數(shù)字與字符串互相轉(zhuǎn)換的實(shí)現(xiàn)示例

    本文主要介紹了C/C++數(shù)字與字符串互相轉(zhuǎn)換的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-02-02
  • 老程序員教你一天時(shí)間完成C語言掃雷游戲

    老程序員教你一天時(shí)間完成C語言掃雷游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)掃雷游戲初級版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • c++函數(shù)指針和回調(diào)函數(shù)示例

    c++函數(shù)指針和回調(diào)函數(shù)示例

    這篇文章主要介紹了c++函數(shù)指針和回調(diào)函數(shù)示例,需要的朋友可以參考下
    2014-05-05
  • c++中的const_cast用法大全

    c++中的const_cast用法大全

    const_cast轉(zhuǎn)換符是用來移除變量的const或volatile限定符。對于后者,我不是太清楚,因?yàn)樗婕暗搅硕嗑€程的設(shè)計(jì),今天重點(diǎn)給大家介紹c++中的const_cast用法大全,需要的朋友參考下吧
    2021-07-07
  • C語言如何實(shí)現(xiàn)Unix時(shí)間戳與本地時(shí)間轉(zhuǎn)化

    C語言如何實(shí)現(xiàn)Unix時(shí)間戳與本地時(shí)間轉(zhuǎn)化

    這篇文章主要介紹了C語言如何實(shí)現(xiàn)Unix時(shí)間戳與本地時(shí)間轉(zhuǎn)化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評論