c++ - 如何从 QVideoWidget 迁移到 QML
问题描述
我有一个 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项目的一部分,这个是抽象工厂生成的QtVideoOutput
C++类调用的类):VideoService
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"
}
我愿意根据您的需要提供任何其他代码或信息。
解决方案
取决于您在何处/如何获取视频纹理数据。(从外观上看,它似乎是你的videoBuffer_
)
您可以简单地创建一个VideoBufferVisualizer
基于QQuickPaintedItem
将缓冲区数据绘制到其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 是如何做到的。
推荐阅读
- c# - Microsoft Teams 通知 CSS 样式
- php - 无法使用 HTML 表和 PHP 显示 JSON 嵌套数组
- typescript - 打字稿:键入一个数组以包含枚举的每个键
- mongodb - 无法为 mongodb 客户端停止 try_for_each_concurrent
- javascript - Apollo 解析器链返回 null
- python - 这个程序的空间复杂度真的是 O(1) 吗?
- spring-boot - 如何使用 SwaggerDefinition 和 oauth2 clientCredential 在 Spring Boot 中启用 Swagger UI Authorize 按钮?
- excel - 损坏的 Excel 文件:这个 xml 修复日志说什么?
- html - x-frame-options 标头集,但仍然可以嵌入 iframe?
- javascript - 在工具提示弹出延迟窗口期间工具提示打开变为假时工具提示未关闭