<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux下V4L2框架基于SDL庫本地USB攝像頭監控

嵌入式技術 ? 來源:嵌入式技術 ? 作者:嵌入式技術 ? 2022-12-17 15:37 ? 次閱讀

1.攝像頭框架編程步驟

(1)打開攝像頭設備(/dev/video0 、/dev/video1 );

(2)設置圖像格式:VIDIOC_S_FMT(視頻捕獲格式、圖像顏色數據格式、圖像寬和高);

(3)申請緩沖區:VIDIOC_REQBUFS(緩沖區數量、緩沖映射方式、視頻捕獲格式);

(4)將緩沖區映射到進程空間:VIDIOC_QUERYBUF(要映射的緩沖區下標、緩沖映射方式、視頻捕獲格式);

(5)將緩沖區添加到隊列中:VIDIOC_QBUF(映射的緩沖區下標、緩沖映射方式、視頻捕獲格式);

(6)開啟攝像頭采集:VIDIOC_STREAMON (視頻捕獲格式) (7)從采集隊列中取出圖像數據,通過SDL圖像渲染;

2.攝像頭v4L2框架應用編程示例

#include 
#include 
#include 
#include 
#include 
struct video
{
	int width;//攝像頭采集圖像寬
	int height;//攝像頭采集圖像高
	char *mmapbuf[4];//保存映射的地址
	int mmap_size;/*映射緩沖區大小*/
};
/*攝像頭應用編程框架*/
int Video_Init(u8 *dev,int video_fd,struct video *video_info)
{
    /*1.打開攝像設備文件*/
	video_fd=open(dev,O_RDWR);
	if(video_fd<0)return -1;
    /*2.圖像數據格式*/
	struct v4l2_format video_format;
	memset(&video_format,0,sizeof(struct v4l2_format));
	video_format.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//捕獲格式
	video_format.fmt.pix.width=1920;
	video_format.fmt.pix.height=1080;
	video_format.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
	if(ioctl(video_fd,VIDIOC_S_FMT,&video_format))return -2;
	video_info->width=video_format.fmt.pix.width;
	video_info->height=video_format.fmt.pix.height;
    printf("圖像尺寸:%d * %dn",video_info->width,video_info->height);
    /*3.申請空間*/
	struct v4l2_requestbuffers video_requestbuffers;
	memset(&video_requestbuffers,0,sizeof(struct v4l2_requestbuffers));
	video_requestbuffers.count=4;//緩沖區個數
	video_requestbuffers.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//V4L2捕獲框架格式
	video_requestbuffers.memory=V4L2_MEMORY_MMAP;//內存映射
	if(ioctl(video_fd,VIDIOC_REQBUFS,&video_requestbuffers))return -3;
	printf("緩沖區個數:%dn",video_requestbuffers.count);
	/*4.將緩沖映射到進程空間*/
	int i=0;
	struct v4l2_buffer video_buffer;
	for(i=0;immap_size=video_buffer.length;/*映射大小*/
        video_info->mmapbuf[i]=mmap(NULL,video_buffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,video_buffer.m.offset);
	}
	/*5.將緩沖區添加到采集隊列*/
	for(i=0;i

3.攝像頭采集圖像處理線程

/*線程清理函數*/
void pth_routine(void *arg)
{
    /*關閉攝像頭*/
	free(arg);
	pthread_mutex_lock(&fastmutex);//互斥鎖上鎖
	pthread_cond_broadcast(&cond);//廣播喚醒所有線程
    pthread_mutex_unlock(&fastmutex);//互斥鎖解鎖
	video_flag=0;
	printf("資源清理完成n");
}
/*攝像頭處理線程*/
void *Video_CollectImage(void *arg)
{
	u8 *rgb=malloc(video_info.height*video_info.width*3);//申請圖像數據緩沖區
	if(rgb==NULL)
	{
		pthread_exit(NULL);/*結束線程*/
	}
	pthread_cleanup_push(pth_routine,rgb);
	struct pollfd fds;
	fds.fd=video_fd;//監聽攝像頭描述符
	fds.events=POLLIN;//讀事件
	fds.revents=0;
	struct v4l2_buffer video_buff;
	while(video_flag)
	{
		poll(&fds,1,-1);
		/*1.從隊列中取數據*/
		memset(&video_buff,0,sizeof(struct v4l2_buffer));
		video_buff.memory=V4L2_MEMORY_MMAP;//內存映射
		video_buff.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//V4L2視頻捕獲
		if(ioctl(video_fd,VIDIOC_DQBUF,&video_buff))break;
		/*yuv轉RGB*/
		yuv_to_rgb(video_info.mmapbuf[video_buff.index],rgb,video_info.width,video_info.height);//顏色數據轉換
        pthread_mutex_lock(&fastmutex);//互斥鎖上鎖
        memcpy(rgb_buff,rgb,video_info.height*video_info.width*3);
        pthread_cond_broadcast(&cond);//廣播喚醒所有線程
        pthread_mutex_unlock(&fastmutex);//互斥鎖解鎖
		/*3.將緩沖區添加到隊列*/
		if(ioctl(video_fd,VIDIOC_QBUF,&video_buff))break;
	}
	pthread_cleanup_pop(1);/*注銷清理函數*/
}

4.YUYV(YUV422)轉RGB888

/*YUYV轉RGB888*/
void yuv_to_rgb(unsigned char *yuv_buffer,unsigned char *rgb_buffer,int iWidth,int iHeight)
{
	int x;
	int z=0;
	unsigned char *ptr = rgb_buffer;
	unsigned char *yuyv= yuv_buffer;
	for (x = 0; x < iWidth*iHeight; x++)
	{
		int r, g, b;
		int y, u, v;
		if (!z)
		y = yuyv[0] << 8;
		else
		y = yuyv[2] << 8;
		u = yuyv[1] - 128;
		v = yuyv[3] - 128;
		b = (y + (359 * v)) >> 8;
		g = (y - (88 * u) - (183 * v)) >> 8;
		r = (y + (454 * u)) >> 8;
		*(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);
		*(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);
		*(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);
		if(z++)
		{
			z = 0;
			yuyv += 4;
		}
	}
}

5.主函數main.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "video.h"

#define CAMERA_DEV "/dev/video0" //攝像頭設備節點
int video_fd;/*攝像頭描述符*/
struct video video_info;/*攝像頭結構體信息*/
void *Video_CollectImage(void *arg);/*攝像頭圖像采集*/
u8 *rgb_buff=NULL;
u8 video_flag=1;
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;//互斥鎖
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//條件變量
typedef enum
{
	false=0,
	true,
}bool;
int main()
{
    /*初始化攝像頭*/
    video_fd=Video_Init(CAMERA_DEV,video_fd,&video_info);
    if(video_fd<=0)
    {
        printf("攝像頭初始化失敗,res=%dn",video_fd);
        return 0;
    }    
    /*創建窗口 */
	SDL_Window *window=SDL_CreateWindow("SDL_VIDEO", SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,800,480,SDL_WINDOW_ALLOW_HIGHDPI|SDL_WINDOW_RESIZABLE);
    /*創建渲染器*/
	SDL_Renderer *render=SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);
	/*清空渲染器*/
	SDL_RenderClear(render);
    printf("圖像尺寸:%d * %dn",video_info.width,video_info.height);
    /*創建紋理*/
	SDL_Texture*sdltext=SDL_CreateTexture(render,SDL_PIXELFORMAT_RGB24,SDL_TEXTUREACCESS_STREAMING,video_info.width,video_info.height);
    /*創建攝像頭采集線程*/
    u8 *rgb_data=malloc(video_info.height*video_info.width*3);
    rgb_buff=malloc(video_info.height*video_info.width*3);//保存RGB顏色數據
   //printf("size=%dn",video_info.mmap_size);
    video_flag=1;/*攝像頭采集標志*/
    pthread_t pthid;
    pthread_create(&pthid,NULL,Video_CollectImage, NULL);
    bool quit=true;
	SDL_Event event;
	SDL_Rect rect;
	while(quit)
	{
		while(SDL_PollEvent(&event))/*事件監測*/
		{
			if(event.type==SDL_QUIT)/*退出事件*/
			{
				quit=false;
				video_flag=0;
				pthread_cancel(pthid);/*殺死指定線程*/
				continue;
			}
		}
		if(!video_flag)
		{
			quit=false;
			continue;
		}
		pthread_mutex_lock(&fastmutex);//互斥鎖上鎖
		pthread_cond_wait(&cond,&fastmutex);
		memcpy(rgb_data,rgb_buff,video_info.height*video_info.width*3);
		pthread_mutex_unlock(&fastmutex);//互斥鎖解鎖
		SDL_UpdateTexture(sdltext,NULL,rgb_data, video_info.width*3);
		//SDL_RenderCopy(render, sdltext, NULL,NULL); // 拷貝紋理到渲染器
		SDL_RenderCopyEx(render, sdltext,NULL,NULL,0,NULL,SDL_FLIP_NONE);
		SDL_RenderPresent(render); // 渲染
	}
    SDL_DestroyTexture(sdltext);/*銷毀紋理*/
    SDL_DestroyRenderer(render);/*銷毀渲染器*/
    SDL_DestroyWindow(window);/*銷毀窗口 */
    SDL_Quit();/*關閉SDL*/
    pthread_mutex_destroy(&fastmutex);/*銷毀互斥鎖*/
    pthread_cond_destroy(&cond);/*銷毀條件變量*/
	free(rgb_buff);
	free(rgb_data);
}

6.運行效果

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASVRf6Zi_5rC0,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center








審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux系統
    +關注

    關注

    4

    文章

    567

    瀏覽量

    26926
  • 嵌入式技術
    +關注

    關注

    10

    文章

    349

    瀏覽量

    34283
  • USB攝像頭
    +關注

    關注

    0

    文章

    22

    瀏覽量

    11191
收藏 人收藏

    評論

    相關推薦

    全志D1-H開發板USB攝像頭拍照Demo

    如:FFmpeg和OpenCV對V4L2均支持。 本例就使用V4L2完成攝像頭對圖片的捕捉,并將其保存為一張圖片。 依照Tina SKD
    發表于 03-04 10:48

    如何在Raspberry Pi(樹莓派)上調用V4L2來操縱攝像頭拍照

    如何在Raspberry Pi(樹莓派)上調用V4L2來操縱攝像頭拍照簡單地說,它就是一個基于ARM CPU的、信用卡那么大的迷你計算機。我曾經寫過一篇教程,展示了如何調用OpenCV,來控制攝像頭
    發表于 06-30 21:39

    【WRTnode2R試用體驗】使用V4L2獲取攝像頭的信息

    V4L2全稱是Video for Linux 2,通過它可以驅動攝像頭。在Ubuntu中,已經內置了V4L2,因此不需要安裝多余的東西。在W
    發表于 10-26 20:36

    CSI攝像頭接口及在英創主板上的應用

    加載相應的驅動,加載驅動后會自動生成設備節點:“/dev/video0",應用程序可以操作該設備節點對攝像頭進行圖像的采集和控制?! SI攝像頭都是用了V4L2驅動提供的標準API來操作
    發表于 10-20 13:36

    【100ASK_IMX6ULL(帶屏) 開發板試用體驗】基于samba v4l2和libjpeg遠程攝像頭圖像讀取

    100ms,這個效率對于網絡監控行業來說完全沒法達到及格水準,但是對于IMX6ULL這樣性能入門的主控來說是這樣的了。使用v4l2進行攝像頭圖像采集的代碼之前已經放出過了,今天放調用
    發表于 11-07 16:33

    香橙派OrangePi PC Plus開發板連接5MP攝像頭測試

    排線接到開發板的 CIS 攝像頭接口上,接好攝 像后再啟動 linux 系統(不要在上電后再插入攝像頭)3) 進入系統后查看下 ov5640 4
    發表于 05-20 15:34

    全志H3芯片香橙派OrangePi PC開發板連接USB攝像頭測試說明

    v4l2 中的 l 是小寫字母 l,不是數字 1)命令查看下 USB 攝像頭的設備節點,從下面的輸出可知
    發表于 06-08 11:34

    全志H2芯片香橙派Zero開發板連接USB攝像頭的使用方法

    使用 lsmod 查看系統是否自動加載了 uvcvideo 內核模塊3) 然后通過 v4l2-ctl(注意 v4l2 中的 l 是小寫字母 l,不是數字 1)命令查看下
    發表于 10-28 17:23

    全志H5芯片開發板香橙派PC2Linux系統連接USB攝像頭的使用方法

    v4l2 中的 l 是小寫字母 l,不是數字 1)命令查看下 USB 攝像頭的設備節點,從下面的輸出可知
    發表于 11-16 11:41

    【觸覺智能 IDO-SBC2D06-V1B-12W開發板試用】USB接口UVC攝像頭

    識別到了攝像頭,說明系統自帶了UVC驅動:可見生成了/dev/video0節點。V4L2是Video for linux2的簡稱,為linux中關于視頻設備的內核驅動。在
    發表于 12-12 20:38

    運行linuxtv官網的v4l2代碼,capture攝像頭時select超時怎么解決?

    編譯,運行linuxtv官網的v4l2代碼,capture 攝像頭時select超時,這怎么搞?
    發表于 12-31 06:12

    運行linuxtv官網的v4l2代碼,capture攝像頭時select超時怎么解決?

    [td]編譯,運行linuxtv官網的v4l2代碼,capture 攝像頭時select超時,這怎么搞?
    發表于 01-14 07:02

    什么是V4L2?有何作用

    1.什么是V4L2Video for(4) Linux 2 的簡稱,V4L的升級版。V4L2
    發表于 01-17 09:05

    Linux驅動的使用

    圖片的保存4、瀏覽功能的實現三、視頻監控代碼分析1、實時監控2、抓拍圖片3、瀏覽四、家電控制1、家電控制內容2、LED控制方法3、
    發表于 02-16 07:19

    如何在OKMX6UL-C上利用攝像頭做圖像采集呢

    攝像頭進行圖像采集,大體的框架是什么? 底層驅動和頂層程序顯示需要做些什么?3. 需要用到v4l2、OpenCV等這些程序嗎?不了解利用攝像頭進行圖像采集的過程,感謝各位大神指教
    發表于 12-02 06:49
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>