树莓派学习专题<15>:树莓派学习专题<15>:树莓派5:使用libcamera驱动获取摄像头图像
0. 项目代码
可以从下面获取到项目中的代码。
https://github.com/cdsmakc/h264_codec_base_rpi4b_rpi5_rv1106_visual_studio.git
1. 背景
之前的系列文章,都是在树莓派4上运行的。这两天又买了个树莓派5来测试。满以为重新编译一下就可以运行,结果发现存在很多问题:
- 树莓派5已经不支持硬件编码了,所以只能使用x264编码。
- V4L2在树莓派5上支持不好,之前的代码,VIDIOC_S_PARM命令和VIDIOC_G_PARM命令,在树莓派5上都报错。更关键的是,VIDIOC_STREAMON命令也无法启动流,报告参数错误。翻了树莓派的论坛,官方的回答是,强烈建议使用libcamera驱动替代V4L2驱动。
- 树莓派官方提供了rpicam-xxx系列工具及源码(源码可以github下载)。rpicam-vid中包含了我想要的所有功能,但是代码时C++的(libcamera驱动也是C++的),而且基本使用的都是C++11之后的特性写的,自己又不会C++,折腾了几天,才勉强弄出来一个可以运行的代码。
2. 参考
主要参考libcamera官方的驱动的说明。
一个是驱动的API:
API
另一个是官方的介绍文档,这些文档介绍了libcamera的特性、框架等,最重要的是里面提供了一个示例程序的步骤:
官方文档



基本上,按照上面这篇文章的内容一步一步小心地复制进去,就可以得到一个可运行的代码。
3. 代码
3.1 类定义
class RCE_CAM
{
private :
std::unique_ptr<CameraManager> pobjCameraManager ;
std::shared_ptr<Camera> pobjCamera ;
std::unique_ptr<CameraConfiguration> pobjCameraConfig ;
std::unique_ptr<ControlList> pobjCameraControls ;
FrameBufferAllocator *pobjAllocator ;
std::vector<std::unique_ptr<Request>> vecpobjRequests ;
public :
RCE_CAM(VOID) ;
public :
// camera manager
INT RCE_CAM_StartCameraManager(VOID) ;
VOID RCE_CAM_StopCameraManager(VOID) ;
// list camera and get camera
VOID RCE_CAM_ListCameraId(VOID) ;
INT RCE_CAM_GetCamera(VOID) ;
// acquire / release camera
INT RCE_CAM_AcquireCamera(VOID) ;
VOID RCE_CAM_ReleaseCamera(VOID) ;
// set camera pixel format, resolution, fps
INT RCE_CAM_SetFormat(VOID) ;
VOID RCE_CAM_SetFps(VOID) ;
// buffer
INT RCE_CAM_AllocBuffer(VOID) ;
VOID RCE_CAM_ReleaseBuffer(VOID) ;
// request callback
INT RCE_CAM_SetRequestCb(VOID (*__RequesetCb)(Request *)) ;
VOID RCE_CAM_QueueRequset(Request *pobjRequest){
pobjCamera->queueRequest(pobjRequest);}
//INT RCE_CAM_SetRequestCb(VOID) ;
// camera start / stop
INT RCE_CAM_StartCamera(VOID) ;
VOID RCE_CAM_StopCamera(VOID) ;
// data process
//static VOID RCE_CAM_ProcessData(Request *Request) ;
} ;
3.2 创建、启动与停止CameraManager
程序的第一步是创建和启动CameraManager,这是后续一切摄像头操作的起点。
创建并启动CameraManager:
INT RCE_CAM::RCE_CAM_StartCameraManager(VOID)
{
INT iRetVal = 0 ;
// 创建CameraManager对象
pobjCameraManager = std::make_unique<CameraManager>() ;
// 启动CameraManager
iRetVal = pobjCameraManager->start() ;
if(0 != iRetVal)
{
cout<<"File "<<__FILE__<<", func "<<__func__<<", line"<<__LINE__<<" : "
<<"Start camera manager failed. Return value is "<<iRetVal<<"."<<endl ;
return -1 ;
}
return 0 ;
}
在程序运行结束后,还需要关闭CameraManager:
VOID RCE_CAM::RCE_CAM_StopCameraManager(VOID)
{
pobjCameraManager->stop() ;
}
3.3 获取摄像头
如下代码获取一个摄像头:
INT RCE_CAM::RCE_CAM_GetCamera(VOID)
{
auto cameras = pobjCameraManager->cameras() ;
// 查找摄像头
if (cameras.empty())
{
cout<<"File "<<__FILE__<<", func "<<__func__<<", line"<<__LINE__<<" : "
<<"No cameras were founded on the system."<<endl ;
return -1 ;

最低0.47元/天 解锁文章
1578





