为Subscriber
QML对象提供自定义帧源,究竟需要做些什么?
VideoOutput
本身是否为"来源提供了VideoOuput
类的实例"?
Qt5文件说明了关于提供此问题的事情:
如果要扩展自己的C ++类以进行互操作 VideoOutput,你可以提供一个基于QObject的类 mediaObject属性,公开一个QMediaObject派生类 有一个QVideoRendererControl,或者你可以提供一个QObject 基于类的可写videoSurface属性,可以接受 QAbstractVideo基于表面的类并且可以遵循正确的协议 向其提供QVideoFrame。
根据以下文档,我做了以下事项:
QAbstractVideoSurface
类,它来自myFrameProvider
,具有可写的QObject
属性。videoSurface
类,使其可以在与`VideoOutput'相同的QML上下文中访问窗口小部件。在那之后 - 每当" videSurface"我都会得到段错误。物业访问。 我应该设置自己的视频表面属性吗?
答案 0 :(得分:3)
虽然有类似的问题,但我偶然发现了你的问题。稍后,我找到了一个适合我的解决方案。即使你的问题是较旧的问题而且你可能继续前进,我想分享我的答案,以便可能帮助其他人。
我在“使用低级视频帧”一节的QT documentation中找到了答案。在那里发布的代码片段作为起点非常有用,但我不得不对其进行修改,以便正确地进行操作。最小的工作示例如下所示:
<强> FrameProvider.h 强>
#include <QObject>
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
class FameProvider : public QObject
{
Q_OBJECT
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ videoSurface WRITE setVideoSurface)
public:
QAbstractVideoSurface* videoSurface() const { return m_surface; }
private:
QAbstractVideoSurface *m_surface = NULL;
QVideoSurfaceFormat m_format;
public:
void 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 setFormat(int width, int heigth, int format)
{
QSize size(width, heigth);
QVideoSurfaceFormat format(size, format);
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);
}
}
public slots:
void onNewVideoContentReceived(const QVideoFrame &frame)
{
if (m_surface)
m_surface->present(frame);
}
};
<强> main.qml 强>
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import QtMultimedia 5.4
import com.yourcompany.FrameProvider 1.0
ApplicationWindow {
objectName: "mainWindow"
visible: true
width: 640
height: 480
FrameProvider{
objectName: "provider"
id: provider
}
VideoOutput {
id: display
objectName: "display"
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width
source: provider
}
}
<强>的main.cpp 强>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
// initialize the qml application engine
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
//register the custom control to the qml application engine
qmlRegisterType<FameProvider>("com.yourcompany.FrameProvider", 1, 0, "FrameProvider");
// start the view
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
{
return -1;
}
// find your custom control
QObject *rootObject = engine.rootObjects().first();
Qobject *display = rootObject->findChild<QObject *>("display");
auto provider = qvariant_cast<FameProvider *>(display->property("source"));
// create your custom frame source. This source is expected to have the following public fields and signals:
// - int width
// - int height
// - int format (following QVideoFrame::PixelFormat)
// - signals: void newFrameAvailable(const QVideoFrame &frame);
CustomFramesource source;
// Set the correct format for the video surface (Make sure your selected format is supported by the surface)
provider->setFormat(source.width,source.height, source.format);
// Connect your frame source with the provider
QObject::connect(&source, SIGNAL(newFrameAvailable(const QVideoFrame &)), provider, SLOT(onNewVideoContentReceived(const QVideoFrame &)));
// run the app
int retVal = app.exec();
return 0;
}
MWE是从我的实际代码中压缩而来的,因此未经测试。我希望无论如何都能运行并显示所有需要的步骤。