|
@@ -237,6 +237,10 @@ void AVOpenGLWidget::resizeGL(int width, int height)
|
|
|
// 文本转OpenGL纹理
|
|
// 文本转OpenGL纹理
|
|
|
void AVOpenGLWidget::updateTipTexture()
|
|
void AVOpenGLWidget::updateTipTexture()
|
|
|
{
|
|
{
|
|
|
|
|
+ // 在进行任何GL调用前,确保上下文已当前
|
|
|
|
|
+ bool needMakeCurrent = (QOpenGLContext::currentContext() != context());
|
|
|
|
|
+ if (needMakeCurrent) makeCurrent();
|
|
|
|
|
+
|
|
|
QFont font;
|
|
QFont font;
|
|
|
font.setPointSize(48);
|
|
font.setPointSize(48);
|
|
|
font.setBold(true);
|
|
font.setBold(true);
|
|
@@ -256,6 +260,7 @@ void AVOpenGLWidget::updateTipTexture()
|
|
|
glDeleteTextures(1, &m_tipTexture);
|
|
glDeleteTextures(1, &m_tipTexture);
|
|
|
}
|
|
}
|
|
|
glGenTextures(1, &m_tipTexture);
|
|
glGenTextures(1, &m_tipTexture);
|
|
|
|
|
+ glActiveTexture(GL_TEXTURE0);
|
|
|
glBindTexture(GL_TEXTURE_2D, m_tipTexture);
|
|
glBindTexture(GL_TEXTURE_2D, m_tipTexture);
|
|
|
glTexImage2D(GL_TEXTURE_2D,
|
|
glTexImage2D(GL_TEXTURE_2D,
|
|
|
0,
|
|
0,
|
|
@@ -269,6 +274,8 @@ void AVOpenGLWidget::updateTipTexture()
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
|
+
|
|
|
|
|
+ if (needMakeCurrent) doneCurrent();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 3D绘制方法
|
|
// 3D绘制方法
|
|
@@ -278,6 +285,7 @@ void AVOpenGLWidget::drawNoVideoTip3D()
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
+ glActiveTexture(GL_TEXTURE0);
|
|
|
glBindTexture(GL_TEXTURE_2D, m_tipTexture);
|
|
glBindTexture(GL_TEXTURE_2D, m_tipTexture);
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
glLoadIdentity();
|
|
glLoadIdentity();
|
|
@@ -315,16 +323,42 @@ void AVOpenGLWidget::paintGL()
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
// 绑定纹理并更新数据
|
|
// 绑定纹理并更新数据
|
|
|
|
|
+ glActiveTexture(GL_TEXTURE0);
|
|
|
glBindTexture(GL_TEXTURE_2D, m_textureId);
|
|
glBindTexture(GL_TEXTURE_2D, m_textureId);
|
|
|
- glTexImage2D(GL_TEXTURE_2D,
|
|
|
|
|
- 0,
|
|
|
|
|
- GL_RGBA,
|
|
|
|
|
- m_frameWidth,
|
|
|
|
|
- m_frameHeight,
|
|
|
|
|
- 0,
|
|
|
|
|
- GL_RGBA,
|
|
|
|
|
- GL_UNSIGNED_BYTE,
|
|
|
|
|
- m_frameData);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 设置像素对齐,避免部分驱动在行对齐处理上造成花屏
|
|
|
|
|
+ GLint oldUnpackAlign = 4;
|
|
|
|
|
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &oldUnpackAlign);
|
|
|
|
|
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
|
|
|
+
|
|
|
|
|
+ // 仅当尺寸变化时重新定义纹理,否则使用 glTexSubImage2D 提升稳定性与性能
|
|
|
|
|
+ if (m_texWidth != m_frameWidth || m_texHeight != m_frameHeight) {
|
|
|
|
|
+ glTexImage2D(GL_TEXTURE_2D,
|
|
|
|
|
+ 0,
|
|
|
|
|
+ GL_RGBA,
|
|
|
|
|
+ m_frameWidth,
|
|
|
|
|
+ m_frameHeight,
|
|
|
|
|
+ 0,
|
|
|
|
|
+ GL_RGBA,
|
|
|
|
|
+ GL_UNSIGNED_BYTE,
|
|
|
|
|
+ m_frameData);
|
|
|
|
|
+ m_texWidth = m_frameWidth;
|
|
|
|
|
+ m_texHeight = m_frameHeight;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ glTexSubImage2D(GL_TEXTURE_2D,
|
|
|
|
|
+ 0,
|
|
|
|
|
+ 0,
|
|
|
|
|
+ 0,
|
|
|
|
|
+ m_frameWidth,
|
|
|
|
|
+ m_frameHeight,
|
|
|
|
|
+ GL_RGBA,
|
|
|
|
|
+ GL_UNSIGNED_BYTE,
|
|
|
|
|
+ m_frameData);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 还原像素对齐
|
|
|
|
|
+ glPixelStorei(GL_UNPACK_ALIGNMENT, oldUnpackAlign);
|
|
|
|
|
+
|
|
|
m_program->bind();
|
|
m_program->bind();
|
|
|
m_program->setUniformValue("texture", 0);
|
|
m_program->setUniformValue("texture", 0);
|
|
|
m_program->setUniformValue("uTextureSize", QVector2D(m_frameWidth, m_frameHeight));
|
|
m_program->setUniformValue("uTextureSize", QVector2D(m_frameWidth, m_frameHeight));
|
|
@@ -725,6 +759,9 @@ void AVOpenGLWidget::showEndTip(const QString& tip)
|
|
|
delete[] m_frameData;
|
|
delete[] m_frameData;
|
|
|
m_frameData = nullptr;
|
|
m_frameData = nullptr;
|
|
|
}
|
|
}
|
|
|
|
|
+ // 重置纹理尺寸缓存,确保下次帧到来时重新定义纹理
|
|
|
|
|
+ m_texWidth = 0;
|
|
|
|
|
+ m_texHeight = 0;
|
|
|
updateTipTexture();
|
|
updateTipTexture();
|
|
|
update();
|
|
update();
|
|
|
}
|
|
}
|
|
@@ -762,6 +799,9 @@ void AVOpenGLWidget::onShowYUV(QSharedPointer<VideoFrame> frame)
|
|
|
} else {
|
|
} else {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+ // 尺寸变更,强制重定义纹理
|
|
|
|
|
+ m_texWidth = 0;
|
|
|
|
|
+ m_texHeight = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 确保m_frameData已正确分配
|
|
// 确保m_frameData已正确分配
|
|
@@ -818,6 +858,7 @@ void AVOpenGLWidget::onShowYUV(QSharedPointer<VideoFrame> frame)
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
case AV_PIX_FMT_YUV422P:
|
|
case AV_PIX_FMT_YUV422P:
|
|
|
|
|
+ case AV_PIX_FMT_YUVJ422P:
|
|
|
if (!u || !v)
|
|
if (!u || !v)
|
|
|
return;
|
|
return;
|
|
|
for (int yy = 0; yy < m_frameHeight; ++yy) {
|
|
for (int yy = 0; yy < m_frameHeight; ++yy) {
|
|
@@ -840,6 +881,74 @@ void AVOpenGLWidget::onShowYUV(QSharedPointer<VideoFrame> frame)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case AV_PIX_FMT_YUYV422: // Packed: Y0 U Y1 V
|
|
|
|
|
+ for (int yy = 0; yy < m_frameHeight; ++yy) {
|
|
|
|
|
+ uint8_t* dst = m_frameData + yy * m_frameWidth * 4;
|
|
|
|
|
+ const uint8_t* row = y + yy * lsY;
|
|
|
|
|
+ for (int xx = 0; xx < m_frameWidth; xx += 2) {
|
|
|
|
|
+ int Y0 = row[xx * 2 + 0];
|
|
|
|
|
+ int Uc = row[xx * 2 + 1];
|
|
|
|
|
+ int Y1 = row[xx * 2 + 2];
|
|
|
|
|
+ int Vc = row[xx * 2 + 3];
|
|
|
|
|
+ // pixel 0
|
|
|
|
|
+ {
|
|
|
|
|
+ int C = Y0 - 16, D = Uc - 128, E = Vc - 128;
|
|
|
|
|
+ int R = (298 * C + 409 * E + 128) >> 8;
|
|
|
|
|
+ int G = (298 * C - 100 * D - 208 * E + 128) >> 8;
|
|
|
|
|
+ int B = (298 * C + 516 * D + 128) >> 8;
|
|
|
|
|
+ *dst++ = clamp(R);
|
|
|
|
|
+ *dst++ = clamp(G);
|
|
|
|
|
+ *dst++ = clamp(B);
|
|
|
|
|
+ *dst++ = 255;
|
|
|
|
|
+ }
|
|
|
|
|
+ // pixel 1 shares U/V
|
|
|
|
|
+ {
|
|
|
|
|
+ int C = Y1 - 16, D = Uc - 128, E = Vc - 128;
|
|
|
|
|
+ int R = (298 * C + 409 * E + 128) >> 8;
|
|
|
|
|
+ int G = (298 * C - 100 * D - 208 * E + 128) >> 8;
|
|
|
|
|
+ int B = (298 * C + 516 * D + 128) >> 8;
|
|
|
|
|
+ *dst++ = clamp(R);
|
|
|
|
|
+ *dst++ = clamp(G);
|
|
|
|
|
+ *dst++ = clamp(B);
|
|
|
|
|
+ *dst++ = 255;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case AV_PIX_FMT_UYVY422: // Packed: U Y0 V Y1
|
|
|
|
|
+ for (int yy = 0; yy < m_frameHeight; ++yy) {
|
|
|
|
|
+ uint8_t* dst = m_frameData + yy * m_frameWidth * 4;
|
|
|
|
|
+ const uint8_t* row = y + yy * lsY;
|
|
|
|
|
+ for (int xx = 0; xx < m_frameWidth; xx += 2) {
|
|
|
|
|
+ int Uc = row[xx * 2 + 0];
|
|
|
|
|
+ int Y0 = row[xx * 2 + 1];
|
|
|
|
|
+ int Vc = row[xx * 2 + 2];
|
|
|
|
|
+ int Y1 = row[xx * 2 + 3];
|
|
|
|
|
+ // pixel 0
|
|
|
|
|
+ {
|
|
|
|
|
+ int C = Y0 - 16, D = Uc - 128, E = Vc - 128;
|
|
|
|
|
+ int R = (298 * C + 409 * E + 128) >> 8;
|
|
|
|
|
+ int G = (298 * C - 100 * D - 208 * E + 128) >> 8;
|
|
|
|
|
+ int B = (298 * C + 516 * D + 128) >> 8;
|
|
|
|
|
+ *dst++ = clamp(R);
|
|
|
|
|
+ *dst++ = clamp(G);
|
|
|
|
|
+ *dst++ = clamp(B);
|
|
|
|
|
+ *dst++ = 255;
|
|
|
|
|
+ }
|
|
|
|
|
+ // pixel 1 shares U/V
|
|
|
|
|
+ {
|
|
|
|
|
+ int C = Y1 - 16, D = Uc - 128, E = Vc - 128;
|
|
|
|
|
+ int R = (298 * C + 409 * E + 128) >> 8;
|
|
|
|
|
+ int G = (298 * C - 100 * D - 208 * E + 128) >> 8;
|
|
|
|
|
+ int B = (298 * C + 516 * D + 128) >> 8;
|
|
|
|
|
+ *dst++ = clamp(R);
|
|
|
|
|
+ *dst++ = clamp(G);
|
|
|
|
|
+ *dst++ = clamp(B);
|
|
|
|
|
+ *dst++ = 255;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
case AV_PIX_FMT_YUV444P:
|
|
case AV_PIX_FMT_YUV444P:
|
|
|
if (!u || !v)
|
|
if (!u || !v)
|
|
|
return;
|
|
return;
|