【问题标题】:QAbstractVideoSurface exampleQAbstractVideoSurface 示例
【发布时间】:2014-08-21 05:23:28
【问题描述】:

我正在尝试让自己成为一个具有更多功能的 QML 相机项目,并为VideoOutput 元素提供源。比如这样:

VideoOutput{
    source:mycamera
}
MyCustomCamera{
    id:mycamera
}

in the document it says

如果您正在扩展自己的 C++ 类以与 VideoOutput,您可以提供一个基于 QObject 的类 公开 QMediaObject 派生类的 mediaObject 属性 有一个可用的 QVideoRendererControl,或者你可以提供一个 QObject 具有可写 videoSurface 属性的基于类,该属性可以接受 基于 QAbstractVideoSurface 的类,可以遵循正确的协议 将 QVideoFrames 传递给它。

我尝试给我的对象一个私有属性mediaObject,它是 QCamera 类型,但看起来 QCamera 没有 QVideoRenderControl(或者是我不知道如何正确执行它的错)。

我需要达到我一开始展示的效果,无论如何欢迎。

或者,谁能给我一个简短的例子,说明“接受 blablabla 并遵循正确协议的可写 videoSurace 属性”是什么意思?

【问题讨论】:

  • 您找到解决方案了吗?像你一样,我阅读了文档,但不知道应该如何实现自定义源代码。
  • 这里也一样。这里有什么进展吗?我不确定我应该实现多少类以及哪些已经实现。可惜我们只有一个段落。

标签: c++ qt qml qt5


【解决方案1】:

我无法帮助您解决您的主要问题,但我可以为您提供videoSurface 的用法示例。您可以像这样使用“可写videoSurface”:

我的示例包括三个主要步骤:

  1. 您编写了一个具有 QAbstactVideoSurface 属性的类。这个类将是您的视频提供者,它可以通过调用它的 present() 函数在 VideoOutput 上显示帧。

videoadapter.h

#ifndef VIDEOADAPTER_H
#define VIDEOADAPTER_H
#include <QObject>
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
#include <QTimer>

class VideoAdapter : public QObject
{
  Q_OBJECT
  Q_PROPERTY(QAbstractVideoSurface* videoSurface READ videoSurface WRITE setVideoSurface NOTIFY signalVideoSurfaceChanged)
public:
  explicit VideoAdapter(QObject *parent = nullptr);

  QAbstractVideoSurface *videoSurface() const;
  void setVideoSurface(QAbstractVideoSurface *videoSurface);

signals:
  void signalVideoSurfaceChanged();

private slots:
  void slotTick();

private:
  void startSurface();

private:
  QAbstractVideoSurface *mVideoSurface;
  QVideoSurfaceFormat *mSurfaceFormat;
  QImage *mImage;
  QTimer mTimer;
};

#endif // VIDEOADAPTER_H

videoadapter.cpp

#include "videoadapter.h"
#include <QDebug>

VideoAdapter::VideoAdapter(QObject *parent)
  : QObject(parent), mVideoSurface(nullptr), mSurfaceFormat(nullptr)
{
  mTimer.setInterval(1000);
  connect(&mTimer, &QTimer::timeout, this, &VideoAdapter::slotTick);
}

QAbstractVideoSurface *VideoAdapter::videoSurface() const
{
  return mVideoSurface;
}

void VideoAdapter::setVideoSurface(QAbstractVideoSurface *videoSurface)
{
  if(videoSurface != mVideoSurface)
  {
    mVideoSurface = videoSurface;
    emit signalVideoSurfaceChanged();
    startSurface();

    // This is the test timer that will tick for us to present the image
    // on the video surface
    mTimer.start();
  }
}

void VideoAdapter::slotTick()
{
  QVideoFrame frame(*mImage);
  mVideoSurface->present(frame);
}

void VideoAdapter::startSurface()
{
  mImage = new QImage("../resources/images/test.jpg");
  auto pixelFormat = QVideoFrame::pixelFormatFromImageFormat(mImage->format());
  mSurfaceFormat = new QVideoSurfaceFormat(mImage->size(), pixelFormat);
  if(!mVideoSurface->start(*mSurfaceFormat))
  {
    qDebug() << "Surface couldn't be started!";
  }
}

此类仅加载图像文件并使用计时器显示它,但在您的情况下,您将拥有一个帧源,因此您可以根据需要进行更改。如果您可以将您的框架转换为QImageQVideoFrame,您可以像这样显示它。

  1. 你必须让这个类在 QML 中可用。在我的例子中,我创建了一个对象并通过将其设置为属性使其对 QML 可见。

    int main(int argc, char *argv[])
    {
      QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
      QGuiApplication app(argc, argv);
    
      QQmlApplicationEngine engine;
    
      QQmlDebuggingEnabler enabler;
    
      VideoAdapter adapter;
      // When you do this this object is made visible to QML context with the
      // given name
      engine.rootContext()->setContextProperty("videoAdapter", &adapter);
    
      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);
    
      return app.exec();
    }
    
  2. 您将此对象作为 QML 中的源提供给 VideoOutput。

    Window {
      visible: true
      width: 640
      height: 480
      color: "black"
      title: qsTr("Video Player")
    
      VideoOutput {
        id: videoPlayer
        anchors.fill: parent
        source: videoAdapter
      }
    }
    

正如我所说的,这个例子是一个简单的例子,它只加载一张图片,并且只定期显示一张图片。

这个问题是一个老问题,你可能会继续,但希望这至少可以帮助其他人。

【讨论】:

    【解决方案2】:

    @U.Tuken 提供的代码工作正常,除非我将 Q_PROPERTY 中的属性名称从“videoSurface”更改为任何其他词,否则它不起作用。从 Qt 的角度来看,这是非常奇怪的行为,“videoSurface”只是一个名称。

    另外我得到了错误

    “qt.gui.icc: fromIccProfile: 最小标签大小健全性失败”。

    如果导入的“JPG”格式不正确,则会弹出此错误 as per this link.

    更改“JPG”文件帮助我摆脱了上述警告。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-09
      • 2020-11-23
      • 2011-11-21
      • 2014-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多