1.攝像頭框架編程步驟
(1)打開攝像頭設(shè)備(/dev/video0 、/dev/video1 );
(2)設(shè)置圖像格式:VIDIOC_S_FMT(視頻捕獲格式、圖像顏色數(shù)據(jù)格式、圖像寬和高);
(3)申請緩沖區(qū):VIDIOC_REQBUFS(緩沖區(qū)數(shù)量、緩沖映射方式、視頻捕獲格式);
(4)將緩沖區(qū)映射到進程空間:VIDIOC_QUERYBUF(要映射的緩沖區(qū)下標(biāo)、緩沖映射方式、視頻捕獲格式);
(5)將緩沖區(qū)添加到隊列中:VIDIOC_QBUF(映射的緩沖區(qū)下標(biāo)、緩沖映射方式、視頻捕獲格式);
(6)開啟攝像頭采集:VIDIOC_STREAMON (視頻捕獲格式) (7)從采集隊列中取出圖像數(shù)據(jù),通過SDL圖像渲染;
2.攝像頭v4L2框架應(yīng)用編程示例
#include
#include
#include
#include
#include
struct video
{
int width;//攝像頭采集圖像寬
int height;//攝像頭采集圖像高
char *mmapbuf[4];//保存映射的地址
int mmap_size;/*映射緩沖區(qū)大小*/
};
/*攝像頭應(yīng)用編程框架*/
int Video_Init(u8 *dev,int video_fd,struct video *video_info)
{
/*1.打開攝像設(shè)備文件*/
video_fd=open(dev,O_RDWR);
if(video_fd<0)return -1;
/*2.圖像數(shù)據(jù)格式*/
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;//緩沖區(qū)個數(shù)
video_requestbuffers.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//V4L2捕獲框架格式
video_requestbuffers.memory=V4L2_MEMORY_MMAP;//內(nèi)存映射
if(ioctl(video_fd,VIDIOC_REQBUFS,&video_requestbuffers))return -3;
printf("緩沖區(qū)個數(shù):%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.將緩沖區(qū)添加到采集隊列*/
for(i=0;i
3.攝像頭采集圖像處理線程
/*線程清理函數(shù)*/ void pth_routine(void *arg) { /*關(guān)閉攝像頭*/ 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);//申請圖像數(shù)據(jù)緩沖區(qū) if(rgb==NULL) { pthread_exit(NULL);/*結(jié)束線程*/ } pthread_cleanup_push(pth_routine,rgb); struct pollfd fds; fds.fd=video_fd;//監(jiān)聽攝像頭描述符 fds.events=POLLIN;//讀事件 fds.revents=0; struct v4l2_buffer video_buff; while(video_flag) { poll(&fds,1,-1); /*1.從隊列中取數(shù)據(jù)*/ memset(&video_buff,0,sizeof(struct v4l2_buffer)); video_buff.memory=V4L2_MEMORY_MMAP;//內(nèi)存映射 video_buff.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//V4L2視頻捕獲 if(ioctl(video_fd,VIDIOC_DQBUF,&video_buff))break; /*yuv轉(zhuǎn)RGB*/ yuv_to_rgb(video_info.mmapbuf[video_buff.index],rgb,video_info.width,video_info.height);//顏色數(shù)據(jù)轉(zhuǎn)換 pthread_mutex_lock(&fastmutex);//互斥鎖上鎖 memcpy(rgb_buff,rgb,video_info.height*video_info.width*3); pthread_cond_broadcast(&cond);//廣播喚醒所有線程 pthread_mutex_unlock(&fastmutex);//互斥鎖解鎖 /*3.將緩沖區(qū)添加到隊列*/ if(ioctl(video_fd,VIDIOC_QBUF,&video_buff))break; } pthread_cleanup_pop(1);/*注銷清理函數(shù)*/ }
4.YUYV(YUV422)轉(zhuǎn)RGB888
/*YUYV轉(zhuǎn)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.主函數(shù)main.c
#include
#include
#include
#include
#include
#include
#include
#include
#include "video.h"
#define CAMERA_DEV "/dev/video0" //攝像頭設(shè)備節(jié)點
int video_fd;/*攝像頭描述符*/
struct video video_info;/*攝像頭結(jié)構(gòu)體信息*/
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;
}
/*創(chuàng)建窗口 */
SDL_Window *window=SDL_CreateWindow("SDL_VIDEO", SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,800,480,SDL_WINDOW_ALLOW_HIGHDPI|SDL_WINDOW_RESIZABLE);
/*創(chuàng)建渲染器*/
SDL_Renderer *render=SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);
/*清空渲染器*/
SDL_RenderClear(render);
printf("圖像尺寸:%d * %dn",video_info.width,video_info.height);
/*創(chuàng)建紋理*/
SDL_Texture*sdltext=SDL_CreateTexture(render,SDL_PIXELFORMAT_RGB24,SDL_TEXTUREACCESS_STREAMING,video_info.width,video_info.height);
/*創(chuàng)建攝像頭采集線程*/
u8 *rgb_data=malloc(video_info.height*video_info.width*3);
rgb_buff=malloc(video_info.height*video_info.width*3);//保存RGB顏色數(shù)據(jù)
//printf("size=%dn",video_info.mmap_size);
video_flag=1;/*攝像頭采集標(biāo)志*/
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))/*事件監(jiān)測*/
{
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();/*關(guān)閉SDL*/
pthread_mutex_destroy(&fastmutex);/*銷毀互斥鎖*/
pthread_cond_destroy(&cond);/*銷毀條件變量*/
free(rgb_buff);
free(rgb_data);
}
6.運行效果

審核編輯:劉清
-
Linux系統(tǒng)
+關(guān)注
關(guān)注
4文章
608瀏覽量
29504 -
嵌入式技術(shù)
+關(guān)注
關(guān)注
10文章
366瀏覽量
43114 -
USB攝像頭
+關(guān)注
關(guān)注
0文章
25瀏覽量
11587
發(fā)布評論請先 登錄
Linux下攝像頭應(yīng)用編程
百問網(wǎng)全志系列開發(fā)板攝像頭V4L2編程步驟詳解
如何在Raspberry Pi(樹莓派)上調(diào)用V4L2來操縱攝像頭拍照
【W(wǎng)RTnode2R試用體驗】使用V4L2獲取攝像頭的信息
【100ASK_IMX6ULL(帶屏) 開發(fā)板試用體驗】基于samba v4l2庫和libjpeg遠(yuǎn)程攝像頭圖像讀取
全志H2芯片香橙派Zero開發(fā)板連接USB攝像頭的使用方法
全志H5芯片開發(fā)板香橙派PC2在Linux系統(tǒng)下連接USB攝像頭的使用方法
運行l(wèi)inuxtv官網(wǎng)的v4l2代碼,capture攝像頭時select超時怎么解決?
運行l(wèi)inuxtv官網(wǎng)的v4l2代碼,capture攝像頭時select超時怎么解決?
需要了解Linux V4L2的驅(qū)動架構(gòu)
Linux應(yīng)用開發(fā)【第七章】攝像頭V4L2編程應(yīng)用開發(fā)
如何使用v4l2 API讀取攝像頭

Linux下V4L2框架基于SDL庫本地USB攝像頭監(jiān)控
評論