基于v4l2基础framebuffer播放摄像头

操作步骤:

  1. 打开摄像头设备文件。 int fd=open(”/dev/video0″,O_RDWR);
  2. 打开显示屏设备文件。int fb_fd = open("/dev/fb0", O_RDWR)
  3. ioctl取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability
  4. ioctl选择视频输入,一个视频设备可以有多个视频输入。VIDIOC_S_INPUT,struct v4l2_input
  5. ioctl设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。
    VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format
  6. 向驱动申请帧缓冲,一般不超过5个。struct v4l2_requestbuffers ,查询缓冲区状态后映射到用于空间 VIDIOC_QUERYBUF struct v4l2_buffer mmap,然后将缓冲区放入队列VIDIOC_QBUF
  7. 将申请到的帧缓冲映射到用户空间,这样就可以直接操作采集到的帧了,而不必去复制,用mmap映射;
  8. 将申请到的帧缓冲全部入队列(注意队列满的情况),以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer ,
  9. 开始视频的采集 ,开始流传输 VIDIOC_STREAMON
  10. 出队列以取得已采集数据的帧缓冲,取得原始采集数据。判断缓冲区是否有数据 使用poll函数,缓冲区有数据后取出队列VIDIOC_DQBUF ,
  11. 将VIDIOC_DQBUF 帧缓冲数据 yuyv取出来转化为rgb,再将rgb封装成bmp图片,另外拷贝一份出来送到framebuffer缓冲上显示,即是绘制bmp数据到framebuffer;
  12. 将缓冲重新入队列尾,这样可以循环采集。VIDIOC_QBUF
  13. 停止视频的采集。VIDIOC_STREAMOFF
  14. 关闭视频设备和显示设备。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

你可能感兴趣的:(linux流媒体)