zhuizhu 6 hónapja
szülő
commit
bf76284b49
2 módosított fájl, 122 hozzáadás és 9 törlés
  1. 118 9
      libs/AVPlayer/avopenglwidget.cpp
  2. 4 0
      libs/AVPlayer/avopenglwidget.h

+ 118 - 9
libs/AVPlayer/avopenglwidget.cpp

@@ -237,6 +237,10 @@ void AVOpenGLWidget::resizeGL(int width, int height)
 // 文本转OpenGL纹理
 void AVOpenGLWidget::updateTipTexture()
 {
+    // 在进行任何GL调用前,确保上下文已当前
+    bool needMakeCurrent = (QOpenGLContext::currentContext() != context());
+    if (needMakeCurrent) makeCurrent();
+
     QFont font;
     font.setPointSize(48);
     font.setBold(true);
@@ -256,6 +260,7 @@ void AVOpenGLWidget::updateTipTexture()
         glDeleteTextures(1, &m_tipTexture);
     }
     glGenTextures(1, &m_tipTexture);
+    glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, m_tipTexture);
     glTexImage2D(GL_TEXTURE_2D,
                  0,
@@ -269,6 +274,8 @@ void AVOpenGLWidget::updateTipTexture()
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     glBindTexture(GL_TEXTURE_2D, 0);
+
+    if (needMakeCurrent) doneCurrent();
 }
 
 // 3D绘制方法
@@ -278,6 +285,7 @@ void AVOpenGLWidget::drawNoVideoTip3D()
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glEnable(GL_DEPTH_TEST);
     glEnable(GL_TEXTURE_2D);
+    glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, m_tipTexture);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
@@ -315,16 +323,42 @@ void AVOpenGLWidget::paintGL()
         return;
     }
     // 绑定纹理并更新数据
+    glActiveTexture(GL_TEXTURE0);
     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->setUniformValue("texture", 0);
     m_program->setUniformValue("uTextureSize", QVector2D(m_frameWidth, m_frameHeight));
@@ -725,6 +759,9 @@ void AVOpenGLWidget::showEndTip(const QString& tip)
         delete[] m_frameData;
         m_frameData = nullptr;
     }
+    // 重置纹理尺寸缓存,确保下次帧到来时重新定义纹理
+    m_texWidth = 0;
+    m_texHeight = 0;
     updateTipTexture();
     update();
 }
@@ -762,6 +799,9 @@ void AVOpenGLWidget::onShowYUV(QSharedPointer<VideoFrame> frame)
         } else {
             return;
         }
+        // 尺寸变更,强制重定义纹理
+        m_texWidth = 0;
+        m_texHeight = 0;
     }
 
     // 确保m_frameData已正确分配
@@ -818,6 +858,7 @@ void AVOpenGLWidget::onShowYUV(QSharedPointer<VideoFrame> frame)
         }
         break;
     case AV_PIX_FMT_YUV422P:
+    case AV_PIX_FMT_YUVJ422P:
         if (!u || !v)
             return;
         for (int yy = 0; yy < m_frameHeight; ++yy) {
@@ -840,6 +881,74 @@ void AVOpenGLWidget::onShowYUV(QSharedPointer<VideoFrame> frame)
             }
         }
         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:
         if (!u || !v)
             return;

+ 4 - 0
libs/AVPlayer/avopenglwidget.h

@@ -79,6 +79,10 @@ private:
     int m_frameWidth;
     int m_frameHeight;
     int m_frameFormat; // 可以用来表示像素格式
+    
+    // 记录当前 OpenGL 纹理实际尺寸(用于按需重定义纹理)
+    int m_texWidth = 0;
+    int m_texHeight = 0;
 
     QMutex m_mutex;
     bool m_frameUpdated;