用QML操作QCamera
Operate QCamera with QML
我正在尝试使用探针从 QCamera 获取 QVideoFrame 以对其进行处理,同时我需要将内容显示给 QML VideoOutput。这就是我所做的:
#include <QObject>
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
class FrameProvider: public QObject {
Q_OBJECT
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ getVideoSurface WRITE setVideoSurface NOTIFY videoSurfaceChanged)
public:
FrameProvider(QObject *parent = nullptr)
: QObject(parent) {}
QAbstractVideoSurface* getVideoSurface() const { return m_surface; }
void setVideoSurface(QAbstractVideoSurface *surface) {
if (m_surface != surface && m_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);
}
emit videoSurfaceChanged();
}
public slots:
void setFrame(const QVideoFrame &frame) {
if (m_surface) {
//do processing
m_surface->present(frame);
}
}
signals:
void videoSurfaceChanged();
private:
QAbstractVideoSurface *m_surface = NULL;
QVideoSurfaceFormat m_format;
};
FrameProvider 在其 getFrames 方法中接收来自 QVideoProbe 的帧并对其进行处理,然后将其发送到其 present() 方法以在 QML 中显示。
main(...) {
//some code
auto ctxt = engine.rootContext();
auto camera = new QCamera();
camera->setCaptureMode(QCamera::CaptureVideo);
FrameProvider fp;
auto probe = new QVideoProbe();
if(probe->setSource(camera)) {
QObject::connect(probe, SIGNAL(videoFrameProbed(QVideoFrame)), &fp, SLOT(setFrame(QVideoFrame)));
}
ctxt->setContextProperty("frameProvider", &fp);
camera->start();
engine.load(url);
}
在 QML 中,我只是将其显示为,
VideoOutput {
source: frameProvider
width: 320
height: 480
}
我关注了QT Documentation, this example and that example。
我收到 getFrame 正在接收探测帧的信号,但 QML window 完全空白。
如果平台很重要,我是 运行 Arch Linux 之上的 KDE Plasma。
我错过了什么?
好的,所以我找到了这个问题的答案。其实问题出在QCamera和VideoOutput之间的格式转换上。我刚刚在 FrameProvider 中添加了这段代码,
void setFormat(int width, int height, QVideoFrame::PixelFormat frameFormat) {
QSize size(width, height);
QVideoSurfaceFormat format(size, frameFormat);
m_format = format;
if (m_surface) {
if (m_surface->isActive())
m_surface->stop();
m_format = m_surface->nearestFormat(m_format);
m_surface->start(m_format);
}
}
并在新框架可用时调用它进行转换,例如,
void setFrame(const QVideoFrame &frame) {
if (m_surface) {
//do other processing with the received frame
...
//after you are done with processing
setFormat(frame.width(), frame.height(), frame.pixelFormat());
m_surface->present(frame);
}
}
这解决了我的问题。
我正在尝试使用探针从 QCamera 获取 QVideoFrame 以对其进行处理,同时我需要将内容显示给 QML VideoOutput。这就是我所做的:
#include <QObject>
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
class FrameProvider: public QObject {
Q_OBJECT
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ getVideoSurface WRITE setVideoSurface NOTIFY videoSurfaceChanged)
public:
FrameProvider(QObject *parent = nullptr)
: QObject(parent) {}
QAbstractVideoSurface* getVideoSurface() const { return m_surface; }
void setVideoSurface(QAbstractVideoSurface *surface) {
if (m_surface != surface && m_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);
}
emit videoSurfaceChanged();
}
public slots:
void setFrame(const QVideoFrame &frame) {
if (m_surface) {
//do processing
m_surface->present(frame);
}
}
signals:
void videoSurfaceChanged();
private:
QAbstractVideoSurface *m_surface = NULL;
QVideoSurfaceFormat m_format;
};
FrameProvider 在其 getFrames 方法中接收来自 QVideoProbe 的帧并对其进行处理,然后将其发送到其 present() 方法以在 QML 中显示。
main(...) {
//some code
auto ctxt = engine.rootContext();
auto camera = new QCamera();
camera->setCaptureMode(QCamera::CaptureVideo);
FrameProvider fp;
auto probe = new QVideoProbe();
if(probe->setSource(camera)) {
QObject::connect(probe, SIGNAL(videoFrameProbed(QVideoFrame)), &fp, SLOT(setFrame(QVideoFrame)));
}
ctxt->setContextProperty("frameProvider", &fp);
camera->start();
engine.load(url);
}
在 QML 中,我只是将其显示为,
VideoOutput {
source: frameProvider
width: 320
height: 480
}
我关注了QT Documentation, this example and that example。 我收到 getFrame 正在接收探测帧的信号,但 QML window 完全空白。 如果平台很重要,我是 运行 Arch Linux 之上的 KDE Plasma。 我错过了什么?
好的,所以我找到了这个问题的答案。其实问题出在QCamera和VideoOutput之间的格式转换上。我刚刚在 FrameProvider 中添加了这段代码,
void setFormat(int width, int height, QVideoFrame::PixelFormat frameFormat) {
QSize size(width, height);
QVideoSurfaceFormat format(size, frameFormat);
m_format = format;
if (m_surface) {
if (m_surface->isActive())
m_surface->stop();
m_format = m_surface->nearestFormat(m_format);
m_surface->start(m_format);
}
}
并在新框架可用时调用它进行转换,例如,
void setFrame(const QVideoFrame &frame) {
if (m_surface) {
//do other processing with the received frame
...
//after you are done with processing
setFormat(frame.width(), frame.height(), frame.pixelFormat());
m_surface->present(frame);
}
}
这解决了我的问题。