QCamera相机类提供了一些基本的功能,包括拍照和录制功能(Windows不支持录制视频),但也有很多接口是没有封装的,比如有些UVC摄像头有物理按键,可以进行拍图等操作,但是QCamera没法响应硬件按钮的拍图操作。
网络上的相关代码都是直接封装平台库(如Windows的DirectShow,Linux的V4L2)来支持硬件按钮,比如我之前参考的一些:
https://www.jianshu.com/p/a67b8cfc57c5
https://gitee.com/fsfzp888/UVCCapture/
https://github.com/GoodRon/QtWebcam
https://github.com/liuleidong/UVCCaptureDemo
但是自己封装出来的效果不是太好,总有一些奇怪的BUG。后来查看Qt5文档和源码,QCamera在Windows平台也是封装的DirectShow,代码路径:
Qt\qt-everywhere-src-5.15.2\qtmultimedia\src\plugins\directshow
既然如此,想让QCamera响应硬件按钮的拍图操作,只需要修改下directshow这个插件即可,而其他的视频渲染等功能就不用自己封装了。视频预览和拍图的接口是差不多的,只需要把预览的接口复制粘贴一份稍加修改。(如果要扩展其他功能,也是直接修改相关源码即可)
先在directshowcameraglobal.h加一个GUID声明PIN_CATEGORY_STILL(因为文本不好标注哪些是新增的,所以用的截图,图中红色为新增代码):
在dscamerasession.h和cpp代码里搜m_previewSampleGrabber和m_nullRendererFilter,然后复制粘贴修改一份。有一点不同的就是,预览的接口如果操作失败是直接返回false,但是硬件拍图我们不能直接返回,因为有的相机本身就没对应的接口,直接跳过就好了。
dscamerasession.h:
dscamerasession.cpp:
DirectShowSampleGrabber::bufferAvailable信号表示有数据来了,连接该信号进行处理,然后使用imageCaptured将图片信号发送出去即可。我这里偷懒发的空图,然后在主程序里判断是否为空再主动触发一次拍图。
if (!m_stillSampleGrabber) {
m_stillSampleGrabber = new DirectShowSampleGrabber(this);
connect(m_stillSampleGrabber, &DirectShowSampleGrabber::bufferAvailable,
this, [this](){
qDebug()<<"Still capture bufferAvailable";
emit imageCaptured(-1, QImage());
});
}
void UVCCamera::onImageCaptured(int id, const QImage &preview)
{
//判断是否是我们在plugins里触发的
if (preview.isNull()) {
if (id == -1)
capture(); //主动拍图
return;
}
//... ...
}