【问题标题】:How to migrate from QVideoWidget to QML如何从 QVideoWidget 迁移到 QML
【发布时间】:2021-07-18 20:44:51
【问题描述】:

我有一个 QML 应用程序,我想将使用 QMediaPlayer 和 QVideoWidget 的 C++ 代码集成到该应用程序中。

我知道媒体播放器在 QML 中的工作方式(来自 Qt 的示例):

Item {
    MediaPlayer {
        id: mediaplayer
        source: "groovy_video.mp4"
    }

    VideoOutput {
        anchors.fill: parent
        source: mediaplayer
    }

    MouseArea {
        id: playArea
        anchors.fill: parent
        onPressed: mediaplayer.play();
    }
}

但我正在处理创建 QVideoWidget 的代码。我想摆脱 C++ 端的 QVideoWidget,并将其替换为我可以在 QML 应用程序中显示的内容。

C++端代码如下(项目本身代码比较长,属于openauto项目的一部分,这是抽象工厂生成的C++类VideoService调用的QtVideoOutput类):

QtVideoOutput::QtVideoOutput(configuration::IConfiguration::Pointer configuration)
    : VideoOutput(std::move(configuration))
{
    this->moveToThread(QApplication::instance()->thread());
    connect(this, &QtVideoOutput::startPlayback, this, &QtVideoOutput::onStartPlayback, Qt::QueuedConnection);
    connect(this, &QtVideoOutput::stopPlayback, this, &QtVideoOutput::onStopPlayback, Qt::QueuedConnection);
    QMetaObject::invokeMethod(this, "createVideoOutput", Qt::BlockingQueuedConnection);
}

void QtVideoOutput::createVideoOutput()
{
    OPENAUTO_LOG(debug) << "[QtVideoOutput] create.";
    videoWidget_ = std::make_unique<QVideoWidget>();
    mediaPlayer_ = std::make_unique<QMediaPlayer>(nullptr, QMediaPlayer::StreamPlayback);
}


bool QtVideoOutput::open()
{
    return videoBuffer_.open(QIODevice::ReadWrite);
}

bool QtVideoOutput::init()
{
    emit startPlayback();
    return true;
}

void QtVideoOutput::stop()
{
    emit stopPlayback();
}

void QtVideoOutput::write(uint64_t, const aasdk::common::DataConstBuffer& buffer)
{
    videoBuffer_.write(reinterpret_cast<const char*>(buffer.cdata), buffer.size);
}

void QtVideoOutput::onStartPlayback()
{
    videoWidget_->setAspectRatioMode(Qt::IgnoreAspectRatio);
    videoWidget_->setFocus();
    //videoWidget_->setWindowFlags(Qt::WindowStaysOnTopHint);
    videoWidget_->setFullScreen(true);
    videoWidget_->show();

    mediaPlayer_->setVideoOutput(videoWidget_.get()); // ???
    mediaPlayer_->setMedia(QMediaContent(), &videoBuffer_);
    mediaPlayer_->play();
    OPENAUTO_LOG(debug) << "Player error state -> " << mediaPlayer_->errorString().toStdString();
}

void QtVideoOutput::onStopPlayback()
{
    videoWidget_->hide();
    mediaPlayer_->stop();
}

完整代码见:https://github.com/matt2005/openauto

我最初的计划是在全局上下文中创建一个 QQuick 对象并将其传递给 QML。但我不知道该怎么做。我想知道您对如何摆脱 C++ 端的 videoWidget 并使其使用我在 QML 端可能拥有的 VideoOutput / AbstractSurface 的想法:

VideoOutput {
    anchors.fill: parent
    anchors.verticalCenter: parent.verticalCenter;
    anchors.horizontalCenter: parent.horizontalCenter;
    width: 640
    height: 480
    source: ???
    objectName: "vidout"
}

我愿意提供您需要的任何其他代码或信息。

【问题讨论】:

    标签: c++ qt qml


    【解决方案1】:

    取决于您获取视频纹理数据的位置/方式。 (看样子好像是你的videoBuffer_

    您可以简单地基于QQuickPaintedItem 创建一个VideoBufferVisualizer 类,以在其paint(QPainter *painter) 方法中将缓冲区数据绘制到QtQuickItem。教程:教程:https://doc.qt.io/qt-5/qtquick-customitems-painteditem-example.html

    请注意,在嵌入式系统上,通常有更快的零拷贝方式将视频纹理数据直接获取到 OpenGL 纹理/Qt 快速场景图形中。您可以查看https://github.com/GStreamer/gst-plugins-good/blob/master/ext/qt/gstqtsink.cc,了解 gstreamer 是如何做到的。

    【讨论】:

      猜你喜欢
      • 2018-06-23
      • 2019-11-11
      • 2018-10-28
      • 2010-10-13
      • 2018-10-25
      • 2019-05-31
      • 2016-11-09
      • 2014-02-09
      • 2021-09-01
      相关资源
      最近更新 更多