Qt从5.0开始支持android摄像头,但是目前还没有做到统一完全跨平台API。还需要根据不同的平台系统来处理。这是因为Qt中QImage支持格式不全,现在不支持YUV格式。
Qt中捕获视频流用两种方式:
一、用QCamera::setViewfinder(QAbstractVideoSurface *surface)
- class MyVideoSurface : public QAbstractVideoSurface
- {
- QList<QVideoFrame::PixelFormat> supportedPixelFormats(
- QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const
- {
- Q_UNUSED(handleType);
- // 返回你将处理的格式
- return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_RGB32;
- }
- bool present(const QVideoFrame &frame)
- {
- Q_UNUSED(frame);
- // 处理捕获的帧
- return true;
- }
- };
二、用QVideoProbe
- camera = new QCamera;
- viewfinder = new QCameraViewfinder();
- camera->setViewfinder(viewfinder);
- camera->setCaptureMode(QCamera::CaptureVideo);
- videoProbe = new QVideoProbe(this);
- if (videoProbe->setSource(camera)) {
- // Probing succeeded, videoProbe->isValid() should be true.
- connect(videoProbe, SIGNAL(videoFrameProbed(QVideoFrame)),
- this, SLOT(detectBarcodes(QVideoFrame)));
- }
- camera->start();
- // Viewfinder frames should now also be emitted by
- // the video probe, even in still image capture mode.
- // Another alternative is to install the probe on a
- // QMediaRecorder connected to the camera to get the
- // recorded frames, if they are different from the
- // viewfinder frames.
windows实现了第一种方式,android实现了第二种方式。
windows支持格式为RGB24、RGB32;android支持格式为NV21
下面我对捕获和显示进行了封装:
CaptureVideoFrame.h
- /*
- * 作者:康林(msn、email: kl222@126.com)
- *
- * 从摄像头(QCarmera)或者(Player)中捕获视频帧。
- * 注意:android后景摄像头捕获的视频翻转-90度,前景摄像头翻转90度。
- * 用法:
- * QCamera m_Camera;
- * m_Camera.setCaptureMode(QCamera::CaptureVideo);
- * CCaptureVideoFrame videoFrame;
- * videoFrame.setSource(&m_Camera);
- * 注册SLOT:
- * connect(&videoFrame, SIGNAL(CaptureFrame(const QVideoFrame&)),
- * SLOT(CaptureVideoFrame(const QVideoFrame&)));
- * 在SLOT 中 CaptureVideoFrame(const QVideoFrame&) 处理捕获到的视频帧。
- *
- * 示例代码:
- * QList<QByteArray> device = QCamera::availableDevices();
- * QList<QByteArray>::iterator it;
- * for(it = device.begin(); it != device.end(); it++)
- * {
- * qDebug("Camera:%s", qPrintable(QCamera::deviceDescription(*it)));
- * }
- *
- * QCamera camera(QCamera::availableDevices().at(1));
- * camera.setCaptureMode(QCamera::CaptureVideo);
- * CFrmPlayer player;
- * CCaptureVideoFrame captureVideoFrame;
- * if(captureVideoFrame.setSource(&camera))
- * {
- * qDebug("probe.setSource is ok");
- * player.connect(&captureVideoFrame, SIGNAL(CaptureFrame(QVideoFrame)),
- * SLOT(present(QVideoFrame)));
- * }
- *
- * player.show();
- * player.activateWindow();
- * camera.start();
- */
- #ifndef CAPTUREVIDEOFRAME_H
- #define CAPTUREVIDEOFRAME_H
- #include <QAbstractVideoSurface>
- #include <QVideoProbe>
- #include <QCamera>
- class CCaptureVideoFrame : public QAbstractVideoSurface
- {
- Q_OBJECT
- public:
- explicit CCaptureVideoFrame(QObject *parent = 0);
- virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(
- QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
- bool setSource(QCamera *pCamera);
- signals:
- //视频帧捕获信号
- void CaptureFrame(const QVideoFrame &frame);
- private slots:
- virtual bool present(const QVideoFrame &frame);
- private:
- QVideoProbe m_Probe;//android下,目前只能用probe捕获视频
- };
- #endif // CAPTUREVIDEOFRAME_H
CaptureVideoFrame.cpp
- /** 作者:康林(msn、email: kl222@126.com)*/
- #include "CaptureVideoFrame.h"
- #include <QCamera>
- CCaptureVideoFrame::CCaptureVideoFrame(QObject *parent) :
- QAbstractVideoSurface(parent)
- {
- }
- QList<QVideoFrame::PixelFormat> CCaptureVideoFrame::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
- {
- Q_UNUSED(handleType);
- QList<QVideoFrame::PixelFormat> lst;
- //lst.push_back(QVideoFrame::Format_YUYV);//Qt现在不支持此格式,因为Qt内部用了QImage来处理视频帧。
- lst.push_back(QVideoFrame::Format_RGB32);
- lst.push_back(QVideoFrame::Format_BGR32);
- return lst;
- }
- //捕获视频帧。windows下格式是RGB32;android下是NV21
- bool CCaptureVideoFrame::present(const QVideoFrame &frame)
- {
- qDebug("CCaptureVideoFrame::present format:%d", frame.pixelFormat());
- emit CaptureFrame(frame);
- return true;
- }
- //根据不同的平台,设置捕获方式
- bool CCaptureVideoFrame::setSource(QCamera *pCamera)
- {
- bool ret = true;
- #ifdef ANDROID
- //android下,目前只能用probe捕获视频
- ret = m_Probe.setSource(pCamera);
- if(ret)
- {
- connect(&m_Probe, SIGNAL(videoFrameProbed(QVideoFrame)),
- SLOT(present(QVideoFrame)));
- }
- #else
- //windows下,只能用下面方式捕获视频
- pCamera->setViewfinder(this);
- #endif
- return ret;
- }
QT对摄像头的支持存在的一些问题:
QT得到到捕获帧相关的参数
QT 在windows、linux下捕获视频只有5帧/秒左右,在我的电脑上用时 240ms 左右。在Android手机上可达到15帧/s(60ms左右)。
QT 在 windows、linux下多个摄像头切换正常,但在 android 手机上,前后摄像头不能切换。代码如下:
- void CFrmVideo::on_cmbCamera_currentIndexChanged(int index)
- {
- LOG_MODEL_DEBUG("Video", "CFrmVideo::on_cmbCamera_currentIndexChanged");
- m_CameraPostition = QCamera::availableDevices().at(index);
- OpenCamera();
- LOG_MODEL_DEBUG("Video", "CFrmVideo::on_cmbCamera_currentIndexChanged end");
- }
- int CFrmVideo::OpenCamera()
- {
- if(!m_pCall)
- {
- LOG_MODEL_ERROR("Video", "CFrmVideo::OpenCamera m_pCall is null");
- return -1;
- }
- if(m_pCamera)
- {
- CloseCamera();
- }
- m_pCamera = new QCamera(m_CameraPostition);
- if(!m_pCamera)
- {
- LOG_MODEL_WARNING("Video", "Open carmera fail");
- return -1;
- }
- m_pCamera->setCaptureMode(QCamera::CaptureVideo);
- m_CaptureVideoFrame.setSource(m_pCamera);
- //m_pCamera->load();
- m_pCamera->start();
- return 0;
- }
- int CFrmVideo::CloseCamera()
- {
- if(m_pCamera)
- {
- m_pCamera->stop();
- //m_pCamera->unload();
- delete m_pCamera;
- m_pCamera = NULL;
- }
- return 0;
- }