操作步骤:
- 打开摄像头设备文件。 int fd=open(”/dev/video0″,O_RDWR);
- 打开显示屏设备文件。int fb_fd = open("/dev/fb0", O_RDWR)
- ioctl取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability
- ioctl选择视频输入,一个视频设备可以有多个视频输入。VIDIOC_S_INPUT,struct v4l2_input
- ioctl设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。
VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format - 向驱动申请帧缓冲,一般不超过5个。struct v4l2_requestbuffers ,查询缓冲区状态后映射到用于空间 VIDIOC_QUERYBUF struct v4l2_buffer mmap,然后将缓冲区放入队列VIDIOC_QBUF
- 将申请到的帧缓冲映射到用户空间,这样就可以直接操作采集到的帧了,而不必去复制,用mmap映射;
- 将申请到的帧缓冲全部入队列(注意队列满的情况),以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer ,
- 开始视频的采集 ,开始流传输 VIDIOC_STREAMON
- 出队列以取得已采集数据的帧缓冲,取得原始采集数据。判断缓冲区是否有数据 使用poll函数,缓冲区有数据后取出队列VIDIOC_DQBUF ,
- 将VIDIOC_DQBUF 帧缓冲数据 yuyv取出来转化为rgb,再将rgb封装成bmp图片,另外拷贝一份出来送到framebuffer缓冲上显示,即是绘制bmp数据到framebuffer;
- 将缓冲重新入队列尾,这样可以循环采集。VIDIOC_QBUF
- 停止视频的采集。VIDIOC_STREAMOFF
- 关闭视频设备和显示设备。close(fd); void closefb(void)
yuyv转rgb函数算法实现:
void yuv422_2_rgb()
{
unsigned char YUV[4],RGB[6];
int i,j,k=0;
unsigned int location = 0;
for(i = 0;i < framebuf[buf.index].length; i+=4)
{
YUV[0] = starter[i]; // y
YUV[1] = starter[i+1]; // u
YUV[2] = starter[i+2]; // y
YUV[3] = starter[i+3]; // v
if(YUV[0] < 0){
RGB[0]=0;
RGB[1]=0;
RGB[2]=0;
}else{
RGB[0] = YUV[0] + 1.772*(YUV[1]-128); // b
RGB[1] = YUV[0] - 0.34414*(YUV[1]-128) - 0.71414*(YUV[3]-128); // g
RGB[2] = YUV[0 ]+ 1.402*(YUV[3]-128); // r
}
if(YUV[2] < 0)
{
RGB[3]=0;
RGB[4]=0;
RGB[5]=0;
}else{
RGB[3] = YUV[2] + 1.772*(YUV[1]-128); // b
RGB[4] = YUV[2] - 0.34414*(YUV[1]-128) - 0.71414*(YUV[3]-128); // g
RGB[5] = YUV[2] + 1.402*(YUV[3]-128) ; // r
}
for(j = 0; j < 6; j++){
if(RGB[j] < 0)
RGB[j] = 0;
if(RGB[j] > 255)
RGB[j] = 255;
}
//请记住:扫描行在位图文件中是反向存储的!
if(k%(width*3)==0)//定位存储位置
{
location=(height-k/(width*3))*(width*3);
}
bcopy(RGB,newBuf+location+(k%(width*3)),sizeof(RGB));
k+=6;
}
return ;
}
说明: starter和 newBuf定义的是全局指针变量。
完整代码:https://download.csdn.net/download/qq_40008325/10954558