您现在的位置是:首页 >技术交流 >qt6 qml 显示yuv数据图像网站首页技术交流
qt6 qml 显示yuv数据图像
简介qt6 qml 显示yuv数据图像
利用qml中的VideoOutput
来显示yuv数据
import QtMultimedia
VideoOutput {
id: videoOutput
anchors.fill: parent
Component.onCompleted: {
Config.setSink(videoOutput.videoSink)
}
}
在VideoOutput创建完成时,将VideoOutput
的videoSink指针传入到c++里面
Config.cpp中的setSink函数
Q_INVOKABLE void setSink(QObject *_Sink)
{
qDebug() << _Sink;
sink = (QVideoSink *)_Sink;
emit sinkChanged();
}
如果你不知道怎么将c++类添加到qml属性里:
#include <QQmlContext>
int main(int argc, char *argv[])
{
·········
QQmlApplicationEngine engine;
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);
QQmlContext *ctx = engine.rootContext();
ctx->setContextProperty("Config", config);
engine.load(url);
·········
然后在你接收yuv数据的代码中
static void frameCallback(void *context, unsigned char **data, const int &pix_fmt, const int &width, const int &height)
{
Config *config = (Config *)context;
if (config)
{
if (config->frame.isNull())
{
QVideoFrameFormat::PixelFormat pixel;
switch (pix_fmt) {
case vp::__yuv420p: { pixel = QVideoFrameFormat::Format_YUV420P; } break;
default: { pixel = QVideoFrameFormat::Format_Invalid; } break;
}
qDebug() << pixel << width << height;
config->frame.reset(new QVideoFrame(QVideoFrameFormat(QSize(width, height), pixel)));
}
config->frame->map(QVideoFrame::ReadWrite);
for(int i = 0; i < config->frame->planeCount(); i ++) {
memcpy(config->frame->bits(i), data[i], config->frame->mappedBytes(i));
}
config->frame->unmap();
if (config->sink)
emit config->sink->videoFrameChanged(*config->frame.data());
}
}
config->frame为QVideoFrame
这里只针对yuv420p进行初始化
在QVideoFrame初始化的时候, QVideoFrameFormat::PixelFormat对应你的图像数据格式
按照以往的方法,先将yuv转为rgb然后在传入QQuickImageProvider
中
在qml通过Image
来显示
这样的方法比较麻烦,现在通过VideoOutput
显示将节省很多代码
性能的话没有做测试对比
VideoOutput
输出的图像比例可以调整fillMode
属性
注意在.pro添加multimedia
模块
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。