首页>>科技 >>内容

Linux下基于SDL库的V4L2框架本地USB摄像头监控

发布时间:2023-09-25 21:58:10编辑:温柔的背包来源:

很多朋友对Linux下基于SDL库的V4L2框架本地USB摄像头监控不是很了解,每日小编刚好整理了这方面的知识,今天就来带大家一探究竟。

Linux下基于SDL库的V4L2框架本地USB摄像头监控

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. Camera 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){ video_fd=open(dev,O_RDWR); if(video_fdwidth=video_format.fmt.pix.width;video_info-height=video_format.fmt.pix.height; printf('图像大小: %d * %dn',video_info-width,video_info-height); 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=V 4L2_MEMORY_MMAP ;//内存映射if(ioctl(video_fd,VIDIOC_REQBUFS,video_requestbuffers))return -3;printf('Number of buffers: %dn',video_requestbuffers.count);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);}for(i=0;i

3.相机采集图像处理线程

void pth_routine(void *arg){ free(arg);pthread_mutex_lock(fastmutex);//锁定互斥锁pthread_cond_broadcast(cond);//广播唤醒所有threads 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);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_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);//解锁互斥锁if( ioctl(video_fd,VIDIOC_QBUF,video_buff))break;}pthread_cleanup_pop(1);}

4.YUYV(YUV422)转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;elsey=yuyv[2] 8;g=(y - (88 * u) - (183 * v)) 8;r=(y + (454 * u)) 8;*(ptr++)=(b 255) ? 255 : ((b 255) ? 255 : ((g 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);返回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();pthread_mutex_destroy( fastmutex);/*销毁互斥锁/pthread_cond_destroy(cond);free(rgb_buff);free(rgb_data);}

六、运行效果

评论柳青

以上知识分享希望能够帮助到大家!