QAbstractVideoSurface示例

时间:2014-08-21 05:23:29

标签: c++ qt qml qt5

我试图让自己成为具有更多功能的QML Camera项目,并为VideoOutput元素提供源代码。比如:

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

in the document it says

  

如果要扩展自己的C ++类以进行互操作   VideoOutput,你可以提供一个基于QObject的类   mediaObject属性,公开一个QMediaObject派生类   有一个QVideoRendererControl,或者你可以提供一个QObject   基于类的可写videoSurface属性,可以接受   QAbstractVideo基于表面的类并且可以遵循正确的协议   向其提供QVideoFrame。

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

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

或者其他任何人都可以给我一个简短的例子,说明“一个可写的videoSurace属性,接受blablabla并遵循正确的协议”?

2 个答案:

答案 0 :(得分:3)

我不能帮助您解决主要问题,但可以举一个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!";
  }
}

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

  1. 您必须使此类在QML中可用。就我而言,我创建了一个对象,并通过将其设置为属性使它对QML可见。

    QVideoFrame
  2. 您将此对象作为QML中的源提供给VideoOutput。

    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();
    }
    

正如我所说,这个示例是一个简单的示例,它仅加载一幅图像并且仅定期显示该图像。

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

答案 1 :(得分:0)

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

另外我有错误

<块引用>

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

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

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

感谢提供代码@U.Tuken