好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

视频的采集和动态显示

视频的采集和动态显示

在 (原创)基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集 和 (原创)基于ZedBoard的Webcam设计(二):USB摄像头图片采集+QT显示 两篇博客中,我们完成了ZedBoard上USB摄像头的图片采集,以及将图片显示到Qt界面上。可是毕竟采集和显示到只是一帧图像,并非动态的视频数据。本小节将在介绍V4L2更新视频缓冲的方式、Qt paintEvent更新控件的基础上,实现如何实现视频的动态显示。

更多更新请关注我的博客:@超群天晴  http://www.cnblogs.com/surpassal/

一、V4l2更新缓冲Buffer的方法

 回顾上一节中,我们使用v4l2控制usb 摄像头,对摄像头的静态图片采集流程操作过程可以归纳为:

静态图片采集流程图

所用到的函数和参数都在旁边标注出。可以看到使用命令 VIDIOC_DQBUF 将缓存中的图像帧取出,然后摄像头设备是一直在采集图像,如果没有更新缓存区命令,采集到的新数据是不会被更新到缓存中的。 v4l2提供了与 VIDIOC_DQBUF 命令相对的命令 VIDIOC_QBUF ,我对这个命令的理解就是允许摄像头设备将采集图像更新到缓存区。所以为了实现缓存区图像数据的动态更新,需要在每一次处理完数据后更新缓存区,以便下一次DQBUF获取到的是新的一帧数据。

 

动态视频采集流程

 为此,需要重新定义两个函数,一个我们定义为get_frame,意为获取视频帧:

  1   int  VideoDevice::get_frame( void  **frame_buf, size_t*  len)
   2   {
   3       v4l2_buffer queue_buf;
   4  
  5      queue_buf.type =  V4L2_BUF_TYPE_VIDEO_CAPTURE;
   6      queue_buf.memory =  V4L2_MEMORY_MMAP;
   7  
  8       if (ioctl(fd, VIDIOC_DQBUF, &queue_buf) == - 1  )
   9       {
  10           return   FALSE;
  11       }
  12  
 13      *frame_buf =  buffers[queue_buf.index].start;
  14      *len =  buffers[queue_buf.index].length;
  15      index =  queue_buf.index;
  16  
 17       return   TRUE;
  18  }

一个为free_frame,意为释放视频帧,让出缓存空间准备新的视频帧数据:

  1   int   VideoDevice::free_frame()
   2   {
   3       if (index != - 1  )
   4       {
   5           v4l2_buffer queue_buf;
   6          queue_buf.type =  V4L2_BUF_TYPE_VIDEO_CAPTURE;
   7          queue_buf.memory =  V4L2_MEMORY_MMAP;
   8          queue_buf.index =  index;
   9  
 10           if (ioctl(fd, VIDIOC_QBUF, &queue_buf) == - 1  )
  11           {
  12               return   FALSE;
  13           }
  14           return   TRUE;
  15       }
  16       return   FALSE;
  17  }

  二、Qt的paintEvent事件

在上篇博客里面,我们对采集的的视频帧数据的显示,采用的方法是使用了一个QLabel和QPixmap,并使用loadfromdata函数将采集的数据转为QPixmap中的数据,并显示到QLabel上。这样的做法导致的结果是QLabel和QPixmap数据只能被更新一次,所以只能显示静态图片。

在完成了视频缓存数据更新后,我们所面临的问题就是怎么样才能把这个数据动态显示出来。好在Qt提供了窗口刷新事件paintEvent,在这里,我们可以使用两种方式触发paintEvent事件:

1、使用定时器QTimer,定时为33ms(因为摄像头的帧频为30pfs);

2、不使用定时器,由QLabel自身内容改变产生。这里采用这种方式。paintEvent函数内容:

  1   void  Widget::paintEvent(QPaintEvent * )
   2   {
   3      rs = vd->get_frame(( void  **)&yuv_buffer,& len);
   4      convert_yuv_to_rgb_buffer(yuv_buffer,rgb_buffer, 640 , 480  );
   5  
  6      frame->loadFromData((uchar *)rgb_buffer, 640  *  480  *  3  );
   7  
  8      ui->label->setPixmap(QPixmap::fromImage(* frame,Qt::AutoColor));
   9  
 10      rs = vd-> unget_frame();
  11  }

三、测试效果

在ubuntu上测试通过后,移植到Zedboard上进行测试,测试视频:

==================================

可执行代码下载: zed_webcam_lab3.rar

 

 

分类:  Linux ,  Qt ,  Xilinx ,  ZedBoard ,  Zynq ,  嵌入式

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于视频的采集和动态显示的详细内容...

  阅读:45次