环境
- 操作系统:Ubuntu 20.04LTS
- Qt版本:5.12.8
目标
我的系统中有两个表单,第一个是QOpenGLWidget(override(来播放视频,第二个是一些QVideoWidget(override(来在录像机中播放视频。
问题
当第一个窗体正在播放视频时,我会显示第二个窗体。而第一个窗体无法显示视频。我发现这个代码QMediaPlayer::setVideoOutput(ui->videoWidget)
导致了问题。
系统接口和操作过程
代码
QOpenGLWidget(覆盖(
#ifndef QMYOPENGLWIDGET_H
#define QMYOPENGLWIDGET_H
#include <QOpenGLWidget>
class QMyOpenGLWidget : public QOpenGLWidget
{
Q_OBJECT
public:
explicit QMyOpenGLWidget(QWidget *parent = nullptr);
public:
void setImgData(uchar *data, int width, int height);
protected:
// QOpenGLWidget interface
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
private:
enum {
Left_Bottom_X,
Left_Bottom_Y,
Right_Bottom_X,
Right_Bottom_Y,
Right_Top_X,
Right_Top_Y,
Left_Top_X,
Left_Top_Y,
Pos_Max
};
uchar *imageData_ = nullptr;//图像信息
QSize imageSize_;
GLuint textureId_; //纹理ID
QSize Ortho2DSize_; //窗口尺寸
int vertexPos_[Pos_Max]; //窗口坐标
float texturePos_[Pos_Max]; //纹理坐标
};
//source file
#include "QMyOpenGLWidget.h"
QMyOpenGLWidget::QMyOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
imageData_ = nullptr;
}
//设置图像的rgb数据和长宽数据
void QMyOpenGLWidget::setImgData(uchar *data, int width, int height)
{
this->imageData_ = data;
this->imageSize_.setWidth(width);
this->imageSize_.setHeight(height);
}
void QMyOpenGLWidget::initializeGL()
{
// 生成一个纹理ID
glGenTextures(1, &textureId_);
// 绑定该纹理ID到二维纹理上
glBindTexture(GL_TEXTURE_2D, textureId_);
// 用线性插值实现图像缩放
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
void QMyOpenGLWidget::resizeGL(int w, int h)
{
Ortho2DSize_.setWidth(w);
Ortho2DSize_.setHeight(h);
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Ortho2DSize_.width(), Ortho2DSize_.height(), 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
}
void QMyOpenGLWidget::paintGL()
{
// QPainter painter;//this way also cause the problem
// painter.begin(this);
// QImage img = QImage(imageData_, imageSize_.width(), imageSize_.height(), QImage::Format_RGB888);
// img = img.scaled(this->width(), this->height());
// painter.drawImage(this->geometry(), img);
// painter.end();
// 设置背景颜色
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);//白色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清理颜色和位深使设置的颜色生效
if (imageData_ == nullptr) {
return;
}
glBindTexture(GL_TEXTURE_2D, textureId_);
// 使用图像数据生成纹理
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imageSize_.width(), imageSize_.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, imageData_);
// 顶点坐标保存的是相对于窗口的位置,由于不需要保持视频长宽比例,
vertexPos_[Left_Bottom_X] = 0;
vertexPos_[Left_Bottom_Y] = 0;
vertexPos_[Right_Bottom_X] = Ortho2DSize_.width();
vertexPos_[Right_Bottom_Y] = 0;
vertexPos_[Right_Top_X] = Ortho2DSize_.width();
vertexPos_[Right_Top_Y] = Ortho2DSize_.height();
vertexPos_[Left_Top_X] = 0;
vertexPos_[Left_Top_Y] = Ortho2DSize_.height();
// 纹理坐标点保存的是相对于图片的位置
texturePos_[Left_Bottom_X] = 0.0f;
texturePos_[Left_Bottom_Y] = 0.0f;
texturePos_[Right_Bottom_X] = 1.0f;
texturePos_[Right_Bottom_Y] = 0.0f;
texturePos_[Right_Top_X] = 1.0f;
texturePos_[Right_Top_Y] = 1.0f;
texturePos_[Left_Top_X] = 0.0f;
texturePos_[Left_Top_Y] = 1.0f;
glEnable(GL_TEXTURE_2D);
glBegin(GL_POLYGON);
glTexCoord2d(texturePos_[Left_Bottom_X], texturePos_[Left_Bottom_Y]);
glVertex2d(vertexPos_[Left_Bottom_X], vertexPos_[Left_Bottom_Y]);
glTexCoord2d(texturePos_[Left_Top_X], texturePos_[Left_Top_Y]);
glVertex2d(vertexPos_[Left_Top_X], vertexPos_[Left_Top_Y]);
glTexCoord2d(texturePos_[Right_Top_X], texturePos_[Right_Top_Y]);
glVertex2d(vertexPos_[Right_Top_X], vertexPos_[Right_Top_Y]);
glTexCoord2d(texturePos_[Right_Bottom_X], texturePos_[Right_Bottom_Y]);
glVertex2d(vertexPos_[Right_Bottom_X], vertexPos_[Right_Bottom_Y]);
glEnd();
glDisable(GL_TEXTURE_2D);
}
#endif // QMYOPENGLWIDGET_H
QVideoWidget(覆盖(
//head file
#ifndef QMYVIDEOWIDGET_H
#define QMYVIDEOWIDGET_H
#include <QVideoWidget>
class QMyVideoWidget : public QVideoWidget
{
Q_OBJECT
public:
explicit QMyVideoWidget(QWidget *parent = nullptr);
};
// source file
#include "QMyVideoWidget.h"
QMyVideoWidget::QMyVideoWidget(QWidget *parent) : QVideoWidget(parent)
{
}
#endif // QMYVIDEOWIDGET_H
使用QGraphicsView而不是QVideoWidget。