使用FFMpeg API 获取摄像头的图像数据

摄像头是我们比较常用的外设,很多场景我们都会用到摄像头。比如视频直播、视频监控等各个领域都会用到摄像头。摄像头图像数据的获取,方法有很多,比如可以使用Qt自带的API获取,也可以使用DirectShow、OpenCV、FFMpeg提供的API方式获取(本质上是通过DirectShow)。本篇文章主要讲述使用FFMpeg API获取摄像头的数据信息。

下面是一个简单的摄像头显示的例子的实现效果:
CameraCapture
使用FFMpeg获取摄像头的图像数据基本分为如下步骤:

  1. 使用 av_register_all();avdevice_register_all(); 中注册全部和设备。
  2. 获取摄像头相关信息
  3. 打开摄像头
  4. 获取摄像头数据并渲染显示

1. 获取摄像头的信息

首先要获取当前设备的摄像头列表。主要是摄像头的名称,这里我们使用Qt的API获取。方法如下:

如果想要查看摄像头的具体信息,可以使用FFMpeg命令:

我这里摄像头的名称为 BisonCam, NB Pro

得到的结果如下:
CameraInfo

2. 打开并初始化摄像头

这里直接贴了代码

这里需要注意的有下面几点:

  1. 打开摄像头之前,可以配置一些摄像头配置的参数,比如分辨率、帧率等信息。
  2. 在打开的URL中,一定要使用如下格式 video=你的摄像头名字 。否则,则会打开失败。
  3. 打开摄像头之后的操作,就是FFMpeg的常规操作了,跟打开视频文件、打开音频文件的使用方法差不多,这里就不作过多的说明了。感兴趣的可以阅读我的这篇文章:使用FFMpeg 解码音频文件

3. 获取摄像头数据及渲染

这里我就直接贴出代码了

  1. 使用函数 av_read_frame 获取一帧数据。
  2. 使用 avcodec_send_packetavcodec_receive_frame 解码这一帧视频数据。
  3. 获取 AVFrame 数据并处理, AVFrame 就是解码后的这帧图像数据。

关于渲染
AVFrame 中的数据,它可能是 RGB24 类型的,也可能是 YUV 类型的。 AVFrame中的 format 记录这图像的数据格式。 我这里根据数据的类型,分别做了处理。如果是YUV的数据,使用 OepnGL 渲染YUV的数据,其他类类型的数据, 使用 SWS 方法转成RGB的数据显示。(使用GPU解码YUV并渲染,效率会更高一下),当然也可以使用SDL渲染。

SWS 使用也很简单:

对于YUV的数据,处理存在 lineSize 中的大小比实际的数据大的情况,也就是说如果分辨率为 1280*720,实际存储的数据可能会比这个偏大(每一行都会多出一部分数据)。lineSize 表示每一行的大小,一共有 Height 个行。这里贴出我处理的代码:

data[0] 和 linesize[0] 表示Y分量的数据和一行数据的大小
data[1] 和 linesize[1] 表示U分量的数据和一行数据的大小
data[2] 和 linesize[U2] 表示V分量的数据和一行数据的大小

函数 convertDeprecatedFormat 是一个格式转换的函数,目的是有些被废弃的格式得到转换,比如说 AV_PIX_FMT_YUVJ420PAV_PIX_FMT_YUV420P 实际上是一样的。

实现代码如下:


完整代码:
头文件 CameraCapture.h

源文件 CameraCapture.cpp

线程中,调用部分:
头文件 CameraCaptureThread.h

cpp文件 CameraCaptureThread.cpp

如果想打开摄像头 直接使用函数 openCamera 打开摄像头就可以了,关联信号 needUpdate 刷界面显示即可。

我这里关联的槽函数

关于使用OpenGL渲染YUV数据,后面的文章会做相关的讲解。

About the Author: admin

喜欢编程、爱游戏,更爱生活。

发表评论

电子邮件地址不会被公开。