c++传递视频流到qml 的 VideoOutput
QT官方文档里面介绍的方法 Video Overview
继承QObject,实现属性, 具有可读写videoSurface属性
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ videoSurface WRITE setVideoSurface)
举例:
FrameProvider.h
#ifndef FRAMEPRODER_H
#define FRAMEPRODER_H
#include <QObject>
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
/*!
* \brief FrameProvider 作为qml VideoOutput.source
*/
class FrameProvider : public QObject
{
Q_OBJECT
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ videoSurface WRITE setVideoSurface)
public:
FrameProvider();
~FrameProvider();
QAbstractVideoSurface *videoSurface() const;
/*!
* \brief 可设置外部自定义QAbstractVideoSurface
* \param surface
*/
void setVideoSurface(QAbstractVideoSurface *surface);
/*!
* \brief 设置视频格式
* \param width 视频宽
* \param heigth 视频高
* \param format enum QVideoFrame::PixelFormat
*/
void setFormat(int width, int heigth, QVideoFrame::PixelFormat format);
public slots:
/*!
* \brief 接收外部数据源,视频帧
* \param frame
*/
void onNewVideoContentReceived(const QVideoFrame &frame);
private:
QAbstractVideoSurface *m_surface = NULL;
QVideoSurfaceFormat m_format;
};
#endif // FRAMEPRODER_H
FrameProvider.cpp
#include "frameproder.h"
FrameProvider::FrameProvider()
{
}
FrameProvider::~FrameProvider()
{
}
QAbstractVideoSurface *FrameProvider::videoSurface() const {
return m_surface;
}
void FrameProvider::setVideoSurface(QAbstractVideoSurface *surface)
{
if (m_surface && m_surface != surface && m_surface->isActive()) {
m_surface->stop();
}
m_surface = surface;
if (m_surface && m_format.isValid())
{
m_format = m_surface->nearestFormat(m_format);
m_surface->start(m_format);
}
}
void FrameProvider::setFormat(int width, int heigth, QVideoFrame::PixelFormat format)
{
QSize size(width, heigth);
QVideoSurfaceFormat vsformat(size, format);
m_format = vsformat;
if (m_surface)
{
if (m_surface->isActive())
{
m_surface->stop();
}
m_format = m_surface->nearestFormat(m_format);
m_surface->start(m_format);
}
}
void FrameProvider::onNewVideoContentReceived(const QVideoFrame &frame)
{
//按照视频帧设置格式
setFormat(frame.width(),frame.height(),frame.pixelFormat());
if (m_surface)
m_surface->present(frame);
}
main.cpp
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
foreach (const QCameraInfo &cameraInfo, cameras) {
qDebug()<<"name: "<<cameraInfo.deviceName()<<" \n description"<<cameraInfo.description();
}
//相机
QSharedPointer<QCamera> cameraPtr(new QCamera(cameras.at(0)));
//取景器
QSharedPointer<MyVideoSurface> surface(new MyVideoSurface);
cameraPtr.get()->setViewfinder(qobject_cast<MyVideoSurface*>(surface.get()));
//QWidget 视频输出界面
//QSharedPointer<VideoOut> videoView(new VideoOut );
//QObject::connect(surface.get(),&MyVideoSurface::imageChanged,videoView.get(),&VideoOut::onFrameChanged);
//videoView->setWindowTitle("QWidget Camera");
//videoView->show();
//qml 视频输出界面
QSharedPointer<FrameProvider> provider( new FrameProvider());
QObject::connect(surface.get(),&MyVideoSurface::frameChanged,provider.get(),&FrameProvider::onNewVideoContentReceived);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("_provider",provider.get());
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
cameraPtr->start();
//simple case
// QSharedPointer<QCamera> cameraPtr1(new QCamera(cameras.at(1)));
// QSharedPointer<QCameraViewfinder> viewfinder(new QCameraViewfinder());
// viewfinder->resize(400,400);
// cameraPtr1->setViewfinder(viewfinder.get());
// viewfinder->show();
// cameraPtr1->start();
return app.exec();
}
qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtMultimedia 5.12
Window {
width: 640
height: 480
visible: true
title: qsTr("qml camera")
// Camera{
// id:cameraDev
// imageProcessing.whiteBalanceMode: CameraImageProcessing.WhiteBalanceFlash
// exposure {
// exposureCompensation: -1.0
// exposureMode: Camera.ExposurePortrait
// }
// flash.mode: Camera.FlashRedEyeReduction
// }
VideoOutput{
source: _provider //cameraDev
anchors.fill: parent
focus : visible
}
}