culturered_client/ProjectorDisplay/DisplayMovieGLWidget.cpp

839 lines
28 KiB
C++
Raw Normal View History

2024-09-07 03:34:44 +00:00
#include "DisplayMovieGLWidget.h"
#include <QApplication>
#include <QDir>
#include <QImageReader>
#include <QPainter>
#include <QDateTime>
#include <QThreadPool>
#include <QStringList>
#include <QOpenGLPixelTransferOptions>
#include "MainWindow.h"
class LoadImageTask : public QObject, public QRunnable {
public:
using HandleResoult = std::function<void(int index, QImage image)>;
public:
LoadImageTask(int index, const QVector<QString>& texturePaths, HandleResoult handle, QObject* parent = nullptr)
: QObject(parent)
, m_index(index)
, m_texturePaths(texturePaths)
, m_handle(std::move(handle)) {
setAutoDelete(true);
}
void run() override {
const QString& path = m_texturePaths[m_index];
QPixmap px(path);
QImage image = px.toImage().mirrored();
m_handle(m_index, std::move(image));
}
private:
int m_index{ 0 };
const QVector<QString>& m_texturePaths;
HandleResoult m_handle;
};
SourImasgeHandler::~SourImasgeHandler() {
}
void SourImasgeHandler::run() {
QImage dest(size_.width(), size_.height(), QImage::Format_RGBA8888);
dest.fill(Qt::transparent);
QImage destAlpha(size_.width(), size_.height(), QImage::Format_RGBA8888);
destAlpha.fill(Qt::transparent);
QPainter painter(&dest);
QPainter painterAlpha(&destAlpha);
QPixmap px(path_);
if (!px.isNull()) {
const QSize& is = MainWindow::Get().GetImageShowSize();
px = px.scaled(is, Qt::KeepAspectRatio);
QPoint sp(abs(size_.width() - px.width()) / 2, abs(size_.height() - px.height()) / 2 - 8);
painter.drawPixmap(sp, px);
QLinearGradient gradient(sp.x(), sp.y(), sp.x() + 100, sp.y());
gradient.setColorAt(0, QColor(255, 255, 255, 0));
gradient.setColorAt(1, QColor(255, 255, 255, 255));
painterAlpha.fillRect(QRect(sp.x(), sp.y(), 100, px.height()), gradient);
QLinearGradient gradientr(sp.x() + px.width() - 100, sp.y(), sp.x() + px.width(), sp.y());
gradientr.setColorAt(0, QColor(255, 255, 225, 255));
gradientr.setColorAt(1, QColor(255, 255, 225, 0));
painterAlpha.fillRect(QRect(sp.x() + px.width() - 100, sp.y(), 100, px.height()), gradientr);
painterAlpha.fillRect(QRect(sp.x() + 100, sp.y(), px.width() - 200, px.height()), Qt::white);
} else {
// qWarning() << "DisplayMovieGLWidget::UpdateSourceImage load failed path:" << path_;
}
dest.mirror();
destAlpha.mirror();
emit Finish(dest, destAlpha);
}
DisplayMovieGLWidget::DisplayMovieGLWidget(QWidget* parent /*= */)
: QOpenGLWidget(parent) {
makeCurrent();
setAutoFillBackground(false);
}
DisplayMovieGLWidget::~DisplayMovieGLWidget() {
//m_vbo.destroy();
if (m_program == nullptr) {
return;
}
makeCurrent();
delete m_background;
delete m_mask;
delete m_source;
delete m_sourceAlpha;
delete m_program;
delete m_vshader;
delete m_fshader;
m_vbo->destroy();
m_vao->destroy();
doneCurrent();
}
void DisplayMovieGLWidget::initializeGL() {
makeCurrent();
initializeOpenGLFunctions();
static float vertices[] = {
// 位置 // 颜色 // 纹理坐标
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上
1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下
-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上
};
static unsigned int indices[] = {
// 注意索引从0开始!
// 此例的索引(0,1,2,3)就是顶点数组vertices的下标
// 这样可以由下标代表顶点组合成矩形
0, 1, 3, // 第一个三角形
1, 2, 3 // 第二个三角形
};
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);// 设置清屏颜色
glDisable(GL_DEPTH_TEST); // 启用深度测试
glEnable(GL_COLOR_BUFFER_BIT); // 启用颜色缓冲区
const QString shaderDir = QApplication::applicationDirPath() + "/ProjectDisplay/shader/";
// 创建顶点着色器对象,并编译
m_vshader = new QOpenGLShader(QOpenGLShader::Vertex);
bool success = m_vshader->compileSourceFile(shaderDir + "vertex_shader.vs");
if (!success) {
const QString log = m_vshader->log();
qDebug() << log;
}
// 创建片段着色器对象,并编译
m_fshader = new QOpenGLShader(QOpenGLShader::Fragment);
success = m_fshader->compileSourceFile(shaderDir + "fragment_shader.fs");
if (!success) {
const QString log = m_fshader->log();
qDebug() << log;
}
// 创建着色器程序对象,添加顶点着色器和片段着色器,并链接它们
m_program = new QOpenGLShaderProgram;
m_program->addShader(m_vshader);
m_program->addShader(m_fshader);
m_program->link();
// 创建顶点数组对象,并绑定到当前上下文
m_vao = new QOpenGLVertexArrayObject;
m_vao->create();
QOpenGLVertexArrayObject::Binder vaoBinder(m_vao);
// 创建顶点缓冲对象,
m_vbo = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
m_vbo->create();
m_vbo->bind();
// 分配显存大小,并搬运至显存
m_vbo->allocate(vertices, sizeof(vertices));
// 创建元素缓冲对象,
m_ebo = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
m_ebo->create();
m_ebo->bind();
// 分配显存大小,并搬运至显存
m_ebo->allocate(indices, sizeof(indices));
// 链接顶点属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0);
// 顶点属性默认是禁用的启用顶点属性0location=0
m_program->enableAttributeArray(0);
// 颜色属性
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
m_program->enableAttributeArray(1);
// 纹理坐标属性
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
m_program->enableAttributeArray(2);
m_vao->release();
m_vbo->release();
QDateTime dt = QDateTime::currentDateTime();
m_startTimestamp = dt.toUTC().toMSecsSinceEpoch();
#ifdef BG_VLC
PlayBackgroundMovie();
#else
InitBackgroundImages();
#endif
InitBackgroundTexture();
InitMaskImages();
InitMaskTexture();
InitForeMovieTextImage();
m_program->bind(); //在修改uniform值之前一定要绑定着色器程序到当前激活的opengl上下文
m_program->setUniformValue("bgMap", 0);
m_program->setUniformValue("maskMap", 1);
m_program->setUniformValue("sourceMap", 2);
m_program->setUniformValue("textMap", 3);
m_program->setUniformValue("movieTextMap", 4);
m_program->setUniformValue("bgMapMask", 5);
m_program->setUniformValue("sourceAlphaMap", 6);
//connect(&m_timer, &QTimer::timeout, this, &DisplayMovieGLWidget::OnTimeout);
//m_timer.start(40);
QTimer::singleShot(3000, [this]() {
m_showSource = true;
}
);
//OnMessage("0|1|0");
//OnMessage("");
}
void DisplayMovieGLWidget::paintGL() {
makeCurrent();
#ifdef BG_VLC
if (!videoImage_.isNull()) {
QOpenGLTexture::PixelFormat pf = QOpenGLTexture::BGRA;
const void* data = reinterpret_cast<const void*>(videoImage_.constBits());
#else
if (m_backgroundFrameCount > 0 && !m_textureData.isEmpty()) {
const QImage& image = m_textureData[m_backgroundCurrentFrame];
QOpenGLTexture::PixelFormat pf = QOpenGLTexture::RGB;
const void* data = reinterpret_cast<const void*>(image.constBits());
#endif
QOpenGLPixelTransferOptions uploadOptions;
uploadOptions.setAlignment(8);
m_background->setData(0, pf, QOpenGLTexture::UInt8, data, &uploadOptions);
}
if (!videoForeImage_.isNull()) {
// const QImage& image = m_textureData[m_backgroundCurrentFrame];
QOpenGLPixelTransferOptions uploadOptions;
uploadOptions.setAlignment(8);
m_movieSource->setData(0, QOpenGLTexture::BGRA, QOpenGLTexture::UInt8, videoForeImage_.constBits(), &uploadOptions);
}
if (m_maskFrame < m_maskTextureData.size() && !m_maskTextureData.isEmpty()) {
const QImage& image = m_maskTextureData[m_maskFrame];
QOpenGLPixelTransferOptions uploadOptions;
uploadOptions.setAlignment(1);
m_mask->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, image.constBits(), &uploadOptions);
//m_mask->setData(image);
}
glClearColor(0.f, 0.f, 0.f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 将纹理绑定到当前激活的纹理单元
if (nullptr != m_background) {
m_background->bind(0);
}
if (nullptr != m_mask) {
m_mask->bind(1);
}
if (nullptr != m_source) {
m_source->bind(2);
}
if (nullptr != m_textSource) {
m_textSource->bind(3);
}
if (nullptr != m_movieSource) {
m_movieSource->bind(4);
}
if (nullptr != m_backgroundMask) {
m_backgroundMask->bind(5);
}
if (nullptr != m_sourceAlpha) {
m_sourceAlpha->bind(6);
}
QMatrix4x4 projection;
QMatrix4x4 view;
view.translate(0.0f, 0.0f, -1.0000f);
QMatrix4x4 model;
// 绑定着色器程序至当前上下文相当于调用glUseProgram()
m_program->bind();
m_program->setUniformValue("view", view);
m_program->setUniformValue("projection", projection);
m_program->setUniformValue("model", model);
QDateTime dt = QDateTime::currentDateTime();
qint64 nowTimeStamp = dt.toUTC().toMSecsSinceEpoch();
float timeStamp = nowTimeStamp - m_startTimestamp;
m_program->setUniformValue("fusion", m_fusion);
m_program->setUniformValue("alpha", m_alpha);
m_program->setUniformValue("time", timeStamp * 0.001f);
// 绑定VAO调用设置的一组状态
QOpenGLVertexArrayObject::Binder vaoBinder(m_vao);
// 绘制三角形
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
m_program->release();
// 交换缓存
auto* context = QOpenGLContext::currentContext();
context->swapBuffers(context->surface());
}
void DisplayMovieGLWidget::resizeGL(int w, int h) {
makeCurrent();
glViewport(0, 0, w, h);
update();
}
#if FPS_DISPLAY
int gettimeofday(struct timeval* tp, struct timezone* tzp) {
// Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
// This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC)
// until 00:00:00 January 1, 1970
static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;
GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time, &file_time);
time = ((uint64_t)file_time.dwLowDateTime);
time += ((uint64_t)file_time.dwHighDateTime) << 32;
tp->tv_sec = (long)((time - EPOCH) / 10000000L);
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
return 0;
}
static double GetFPSAverageCount(int seconds) {
static struct timeval timeStart;
static struct timeval timeFinish;
static bool init{ false };
static int count{ 0 };
static double fps = 0.0;
if (!init) {
gettimeofday(&timeStart, NULL);
gettimeofday(&timeFinish, NULL);
init = true;
} else {
int cycle = timeFinish.tv_sec - timeStart.tv_sec;
gettimeofday(&timeFinish, NULL);
if (cycle >= seconds) {
gettimeofday(&timeStart, NULL);
fps = count / seconds;
count = 0;
printf("----------\n");
printf("%d S average FPS value is: %f\n", seconds, fps);
}
count++;
}
return fps;
}
void DisplayMovieGLWidget::paintEvent(QPaintEvent* event) {
QPainter painter;
painter.begin(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(100, 100);
painter.fillRect(rect(), QBrush(QColor(64, 32, 64)));
painter.setPen(Qt::red);
double fps = GetFPSAverageCount(1);
painter.drawText(rect().topLeft() + QPoint(20, 100), QString("fps:%1").arg(QString::number(fps)));
// painter.drawLine(rect().topLeft(), rect().bottomRight());
painter.end();
}
#endif
void DisplayMovieGLWidget::OnTimeout() {
makeCurrent();
#ifndef BG_VLC
LoadBackgroundTexture();
if (!m_textureData.isEmpty()) {
m_backgroundCurrentFrame = (m_backgroundCurrentFrame + 1) % m_textureData.size();
}
#endif
LoadMaskTexture();
if (++m_maskFrame >= m_maskTextureData.size()) {
m_maskFrame = m_maskTextureData.size() - 1;
}
if (m_showSource && (++m_colorMaskFrame >= m_maskTextureData.size())) {
m_colorMaskFrame = m_maskTextureData.size() - 1;
}
if (m_delayTime > 0) {
m_delayTime -= 40;
if (m_alpha >= 1.0f) {
m_alpha = 1.0f;
} else {
m_alpha *= 1.05f;
}
} else {
if (m_alpha == 0.0f) {
update();
return;
}
if (m_alpha > 0.000001f) {
m_alpha *= 0.95f;
} else {
m_alpha = 0.0f;
m_maskFrame = 0;
m_place = 0;
m_showText = "";
UpdateTextImage();
m_fusion = false;
}
}
emit AlphaChanged(m_alpha);
update();
}
void DisplayMovieGLWidget::OnMoveFrame(const QImage& movieImage) {
videoForeImage_ = movieImage.mirrored();
}
//void DisplayMovieGLWidget::LoadBackgroundTexture() {
// if (m_textureData.count() >= m_backgroundFrameCount) {
// return;
// }
//
// QImageReader reader;
// reader.setAutoTransform(true);
//
// reader.setFileName(m_backgourndTexturePaths[m_backgroundCurrentFrame]);
// QImage image = reader.read();
// image = image.mirrored().convertToFormat(QImage::Format_RGBA8888);
// m_textureData.emplace_back(std::move(image));
//}
void DisplayMovieGLWidget::InitBackgroundImages() {
#ifndef BG_VLC
const QString imageDir = QApplication::applicationDirPath() + "/ProjectDisplay/background/out";
QStringList jpgFiles;
QDir dir(imageDir);
QStringList filters;
filters << "*.jpg"; // 添加 JPG 的文件扩展名
QFileInfoList fileInfoList = dir.entryInfoList(filters, QDir::Files); // 使用过滤器获取文件列表
m_backgroundFrameCount = fileInfoList.size();
m_textureData.resize(m_backgroundFrameCount);
foreach(const QFileInfo & fileInfo, fileInfoList) {
m_backgourndTexturePaths.append(fileInfo.absoluteFilePath());
}
auto handle = [&](int index, QImage image) {
image = image.convertToFormat(QImage::Format_RGB888);
m_textureData[index] = std::move(image);
};
QThreadPool pool;
pool.setMaxThreadCount(std::thread::hardware_concurrency());
for (int i = 0; i < m_backgourndTexturePaths.count(); ++i) {
LoadImageTask* task = new LoadImageTask(i, m_backgourndTexturePaths, handle);
pool.start(task);
}
pool.waitForDone();
#endif
}
void DisplayMovieGLWidget::LoadMaskTexture() {
if (m_maskTextureData.count() >= m_maskFrameCount) {
return;
}
QImageReader reader;
reader.setAutoTransform(true);
reader.setFileName(m_maskTexturePaths[m_maskFrame]);
QSize s = size();
QImage image = reader.read();
image = image.scaled(s, Qt::KeepAspectRatio);
m_maskTextureData.emplace_back(std::move(image.mirrored()));
}
void DisplayMovieGLWidget::InitBackgroundTexture() {
if (nullptr == m_background) {
// QPixmap px(m_backgourndTexturePaths[m_backgroundCurrentFrame]);
m_background = new QOpenGLTexture(QOpenGLTexture::Target2D);
m_background->setAutoMipMapGenerationEnabled(false);
m_background->setSize(3840, 1200);
m_background->setMipLevels(1);
#ifndef BG_VLC
m_background->setFormat(QOpenGLTexture::RGB8_UNorm);
/*m_background->setMinificationFilter(QOpenGLTexture::Nearest);
m_background->setMagnificationFilter(QOpenGLTexture::Nearest);
m_background->allocateStorage();*/
m_background->allocateStorage(QOpenGLTexture::RGB, QOpenGLTexture::UInt8);
#else
m_background->setFormat(QOpenGLTexture::RGBA8_UNorm);
/*m_background->setMinificationFilter(QOpenGLTexture::Nearest);
m_background->setMagnificationFilter(QOpenGLTexture::Nearest);
m_background->allocateStorage();*/
m_background->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
#endif
//// 设置纹理环绕方式
m_background->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
m_background->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
// 设置多级渐远纹理过滤方式
//m_background->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
}
if (nullptr == m_backgroundMask) {
m_backgroundMask = new QOpenGLTexture(QOpenGLTexture::Target2D);
m_backgroundMask->setAutoMipMapGenerationEnabled(false);
m_backgroundMask->setFormat(QOpenGLTexture::RGBA8_UNorm);
m_backgroundMask->setSize(3840, 1200);
m_backgroundMask->setMipLevels(1);
m_backgroundMask->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
m_backgroundMask->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
m_backgroundMask->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
QImageReader reader;
reader.setAutoTransform(true);
const QString filePath = QCoreApplication::applicationDirPath() + "/ProjectDisplay/background/bg.png";
reader.setFileName(filePath);
QImage image = reader.read();
QImage dest(3840, 1200, QImage::Format_RGBA8888);
dest.fill(0);
QPainter painter(&dest);
painter.drawImage(0, 0, image);
painter.end();
dest.mirror();
QOpenGLPixelTransferOptions uploadOptions;
uploadOptions.setAlignment(1);
m_backgroundMask->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, dest.constBits(), &uploadOptions);
}
}
void DisplayMovieGLWidget::InitMaskTexture() {
if (nullptr == m_mask) {
QImageReader reader;
reader.setAutoTransform(true);
reader.setFileName(m_maskTexturePaths[m_maskFrame]);
QImage image = reader.read();
m_mask = new QOpenGLTexture(QOpenGLTexture::Target2D);
m_mask->setAutoMipMapGenerationEnabled(false);
m_mask->setFormat(QOpenGLTexture::RGBA8_UNorm);
int with = image.width();
int height = image.height();
m_mask->setSize(with, height);
m_mask->setMipLevels(1);
m_mask->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
/*m_mask = new QOpenGLTexture(image.mirrored());
m_mask->setAutoMipMapGenerationEnabled(false);*/
// 设置纹理环绕方式
m_mask->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
m_mask->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
}
}
void DisplayMovieGLWidget::UpdateSourceImage(const QString& path) {
if (path.isEmpty()) {
qWarning() << "DisplayMovieGLWidget::UpdateSourceImage source path is empty";
return;
}
const QSize s = size();
if (nullptr == m_source) {
makeCurrent();
m_source = new QOpenGLTexture(QOpenGLTexture::Target2D);
m_source->setAutoMipMapGenerationEnabled(false);
m_source->setFormat(QOpenGLTexture::RGBA8_UNorm);
m_source->setSize(s.width(), s.height());
m_source->setMipLevels(1);
m_source->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
// 设置纹理环绕方式
m_source->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge);
m_source->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge);
}
if (nullptr == m_sourceAlpha) {
makeCurrent();
m_sourceAlpha = new QOpenGLTexture(QOpenGLTexture::Target2D);
m_sourceAlpha->setAutoMipMapGenerationEnabled(false);
m_sourceAlpha->setFormat(QOpenGLTexture::RGBA8_UNorm);
m_sourceAlpha->setSize(s.width(), s.height());
m_sourceAlpha->setMipLevels(1);
m_sourceAlpha->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
// 设置纹理环绕方式
m_sourceAlpha->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge);
m_sourceAlpha->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge);
}
;
SourImasgeHandler* handler = new SourImasgeHandler(path, s);
connect(handler, &SourImasgeHandler::Finish, this, &DisplayMovieGLWidget::OnUpdateSourceImage, Qt::QueuedConnection);
QThreadPool::globalInstance()->start(handler);
}
void DisplayMovieGLWidget::UpdateTextImage() {
makeCurrent();
const QSize s = size();
QImage dest(s.width(), s.height(), QImage::Format_RGB888);
dest.fill(Qt::transparent);
QPainter painter(&dest);
//const QStringList& fontFamilies = MainWindow::Get().GetDefaultFontFamily();
//QFont font(fontFamilies[0], 30, QFont::Black);
QFont font("Microsoft YaHei", 30, QFont::Bold);
painter.setPen(QColor(255, 255, 255));
painter.setFont(font);
QFontMetrics fm(font);
const QSize textSize = fm.size(Qt::TextWordWrap, m_showText);
QTextOption textOption(Qt::AlignHCenter);
textOption.setWrapMode(QTextOption::NoWrap);
painter.drawText(MainWindow::Get().GetTextRect(), m_showText, textOption);
painter.end();
QImage image = dest.mirrored();
if (nullptr == m_textSource) {
//m_textSource = new QOpenGLTexture(image);
m_textSource = new QOpenGLTexture(QOpenGLTexture::Target2D);
m_textSource->setAutoMipMapGenerationEnabled(false);
m_textSource->setFormat(QOpenGLTexture::RGB8_UNorm);
m_textSource->setSize(image.width(), image.height());
m_textSource->setMipLevels(1);
m_textSource->allocateStorage(QOpenGLTexture::RGB, QOpenGLTexture::UInt8);
// 设置纹理环绕方式
m_textSource->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge);
m_textSource->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge);
}
QOpenGLPixelTransferOptions uploadOptions;
uploadOptions.setAlignment(1);
m_textSource->setData(0, QOpenGLTexture::RGB, QOpenGLTexture::UInt8, image.constBits(), &uploadOptions);
//m_textSource->setData(dest.mirrored());
}
void DisplayMovieGLWidget::InitForeMovieTextImage() {
makeCurrent();
QImage dest(3240, 1200, QImage::Format_RGBA8888);
dest.fill(Qt::transparent);
videoForeImage_ = dest.mirrored();
if (nullptr == m_movieSource) {
//m_textSource = new QOpenGLTexture(image);
m_movieSource = new QOpenGLTexture(QOpenGLTexture::Target2D);
m_movieSource->setAutoMipMapGenerationEnabled(false);
m_movieSource->setFormat(QOpenGLTexture::RGBA8_UNorm);
m_movieSource->setSize(dest.width(), dest.height());
m_movieSource->setMipLevels(1);
m_movieSource->allocateStorage(QOpenGLTexture::RGB, QOpenGLTexture::UInt8);
// 设置纹理环绕方式
m_movieSource->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge);
m_movieSource->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge);
}
QOpenGLPixelTransferOptions uploadOptions;
uploadOptions.setAlignment(1);
m_movieSource->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, videoForeImage_.constBits(), &uploadOptions);
}
void DisplayMovieGLWidget::PlayBackgroundMovie() {
#ifdef BG_VLC
videoImage_ = QImage(3840, 1200, QImage::Format_RGBA8888);
connect(&vlcPlayer_, &VlcMediaListPlayer::VideoDataOutput, this, &DisplayMovieGLWidget::SlotSetOneFrame, Qt::QueuedConnection);
vlcPlayer_.SetPlayMode(VlcMediaListPlayer::Loop);
const QString filePath = QCoreApplication::applicationDirPath() + "/ProjectDisplay/background/bg.mp4";
QStringList paths;
paths.append(filePath);
vlcPlayer_.SetResolution(3840, 1200);
vlcPlayer_.SetMediaList(paths);
vlcPlayer_.Play();
#endif
}
void DisplayMovieGLWidget::SlotSetOneFrame(QImage image) {
#ifdef BG_VLC
videoImage_ = image.mirrored();
#endif
}
void DisplayMovieGLWidget::OnUpdateSourceImage(QImage source, QImage sourceAlpha) {
makeCurrent();
QOpenGLPixelTransferOptions uploadOptions;
uploadOptions.setAlignment(1);
m_source->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, source.constBits(), &uploadOptions);
m_sourceAlpha->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, sourceAlpha.constBits(), &uploadOptions);
}
void DisplayMovieGLWidget::LoadBackgroundTexture() {
#ifndef BG_VLC
if (m_textureData.count() >= m_backgroundFrameCount) {
return;
}
QImageReader reader;
reader.setAutoTransform(true);
reader.setFileName(m_backgourndTexturePaths[m_backgroundCurrentFrame]);
QImage image = reader.read();
image = image.mirrored().convertToFormat(QImage::Format_RGB888);
m_textureData.emplace_back(std::move(image));
#endif
}
void DisplayMovieGLWidget::InitMaskImages() {
const QString imageDir = QApplication::applicationDirPath() + "/ProjectDisplay/mask";
QStringList jpgFiles;
QDir dir(imageDir);
QStringList filters;
filters << "*.jpg"; // 添加 JPG 的文件扩展名
QFileInfoList fileInfoList = dir.entryInfoList(filters, QDir::Files); // 使用过滤器获取文件列表
m_maskFrameCount = fileInfoList.size();
m_maskTextureData.resize(fileInfoList.size());
foreach(const QFileInfo & fileInfo, fileInfoList) {
m_maskTexturePaths.append(fileInfo.absoluteFilePath());
}
auto handle = [&](int index, QImage image) {
m_maskTextureData[index] = std::move(image);
};
QThreadPool pool;
pool.setMaxThreadCount(std::thread::hardware_concurrency());
for (int i = 0; i < m_maskTexturePaths.count(); ++i) {
LoadImageTask* task = new LoadImageTask(i, m_maskTexturePaths, handle);
pool.start(task);
}
pool.waitForDone();
}
void DisplayMovieGLWidget::ReInit() {
// m_backgroundCurrentFrame = 0;
m_maskFrame = 0;
m_colorMaskFrame = 0;
m_showSource = false;
QTimer::singleShot(5000, [this]() {
m_showSource = true;
}
);
}
void DisplayMovieGLWidget::SetNetConnectStatus(int connected) {
m_connected = connected;
//UpdateNetworkTextImage();
}
void DisplayMovieGLWidget::OnMessage(const QString& cmd) {
// cmd = "0/0/0"
const QStringList params = cmd.split("|");
if (params.count() < 3) {
qWarning() << "invalid cmd:" << cmd;
return;
}
int32_t town = params[0].toInt();
int32_t place = params[1].toInt();
int32_t image = params[2].toInt();
if (/*m_place != place*/true) {
m_place = place;
m_maskFrame = 0;
m_colorMaskFrame = 0;
m_showSource = false;
QDateTime dt = QDateTime::currentDateTime();
m_startTimestamp = dt.toUTC().toMSecsSinceEpoch();
QTimer::singleShot(5000, [this]() {
m_showSource = true;
});
QTimer::singleShot(100, [this]() {
MainWindow::Get().PlayWav();
});
}
m_alpha = 0.13f;
const QString townName = MainWindow::Get().GetTownName(town);
const QString placeName = MainWindow::Get().GetPlaceName(town, place);
const QString imageName = MainWindow::Get().GetImageName(town, place, image);
/*if (imageName.isEmpty()) {
qWarning() << "image name is empty";
return;
}*/
const QString& path = QString("%1/ProjectDisplay/images/%2/%3/%4").arg(QApplication::applicationDirPath(), townName, placeName, imageName);
UpdateSourceImage(path);
m_showText = MainWindow::Get().GetTitleName(town, place);
UpdateTextImage();
m_fusion = true;
m_delayTime = MainWindow::Get().GetDelayRetore() * 1000;
}