基于嵌入式Linux的视频采集编码系统实现三
3. 设置窗口的高度和宽度
编码器输入的是 CIF 格式的YUV420 码流,故将采集窗口的高度设置为 288,宽度为352。
4. 获取视频帧
使用mmap()(内存映射) 方式截取视频,mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。[5]
主要部分介绍如下:
a. 初始化及设置
使用ioctl(camera_fd,VIDIOCGMBUF,camera_mbuf) 函数初始video_mbuf,获得摄像头存储缓冲区的帧信息,之后修改 video_mmap和帧状态的设置。
b. 实现摄像头设备文件到内存区的映射
调用buf=void *mmap(void *addr,size_t len,int prot,int flags,int fd,off_t offset) 函数,将设备文件的内容映射到内存区。
c. 数据采集
调用ioctl(fd,VIDIOCMCAPTURE,camera_buf)截取图像,失败将返回-1 ,若函数成功调用,便开始一帧图像数据的截取,并将当前帧号按缓冲区总帧数的模加上1,为下一帧截取作准备。然后调用 ioctl(fd,VIDIOCSYNC,frame) 函数,成功返回则表示图像截取已完成,可以开始作下一帧图像的采集。图像捕捉函数 v41_frame_grab()是mmap内存映射方式捕捉视频数据的具体实现,每次采集一帧YUV420P格式的原始图像数据。在使用双缓冲区轮换采集时,对于每个缓冲区进行连续帧采集,通过外加循环控制对摄像头帧缓冲区采集的次数来实现,以达到提高效率的目的[6]。
在此基础上也可实现连续帧的采集,Video4Linux最多支持一次采集32帧,首先需要设置采集的帧数 camera_buf.frame,并将data+camera_mbuf.offsets[frame] 定义每一帧数据在内存中的起始位置,利用 ioctl(fd,VIDIOCGMBUF,camera_mbuf) 便可获得camera_mbuf 的信息。除此之外还要设置数据缓冲区的大小,然后利用 ioctl VIDIOCMCAPTURE 操作进行数据的连续采集,直到缓冲区中的剩余空间无法保存一个完整的数据帧。当缓冲区中没有可利用的空间时,系统调用 ioctl VIDIOCSYNC 来检查视频采集过程是否完成。若完成时,应用程序为数据帧分配地址,使缓冲区的数据帧可被安全用于其他进程。
4. 关闭视频设备
在采集完成后,需要关闭设备,并收回系统资源。如果是采用内存映射方法进行视频采集,在系统任务完成后必须用munmap 函数关闭映射内存,close函数可关闭视频设备文件。
5视频采集系统的多线程设计
在采集和处理模块的设计中创建图像采集和图像处理两个线程,并开辟两个缓冲区轮换采集图像帧,以便解决视频采集模块与编码模块的同步。在采集程序写满缓冲区1 后,改变线程等待条件,释放被阻塞的图像处理线程对该缓冲区数据进行编码输出。同时采集线程转到缓冲区2,若此时图像处理线程已完成对缓冲区 2 的处理,则将采集获得的帧图像覆盖,保存至缓冲区 2,否则阻塞。两个缓冲轮流使用,不丢弃任何帧,并且图像采集与处理同步进行,提高了效率。
![](https://webstorage.eepw.com.cn/images/display/reg.jpg)
评论