zhuizhu пре 9 месеци
родитељ
комит
b1be7b7bc3

+ 13 - 0
AvPlayer/playerdemowindow.cpp

@@ -33,6 +33,10 @@ PlayerDemoWindow::PlayerDemoWindow(QWidget* parent)
     controlLayout->addWidget(m_playBtn);
     controlLayout->addWidget(new QLabel("倍速:", this));
     controlLayout->addWidget(m_speedCombo);
+    // 添加保持比例复选框
+    m_keepAspectCheck = new QCheckBox("保持比例", this);
+    m_keepAspectCheck->setChecked(true);
+    controlLayout->addWidget(m_keepAspectCheck);
     layout->addLayout(controlLayout);
 
     m_speedCombo->setCurrentText("1.0x");
@@ -48,6 +52,9 @@ PlayerDemoWindow::PlayerDemoWindow(QWidget* parent)
             this,
             &PlayerDemoWindow::onSpeedChanged);
     connect(m_playBtn, &QPushButton::clicked, this, &PlayerDemoWindow::onPlayClicked);
+    connect(m_keepAspectCheck, &QCheckBox::toggled, this, [this](bool checked) {
+        m_videoWidget->setKeepAspectRatio(checked);
+    });
 }
 
 PlayerDemoWindow::~PlayerDemoWindow()
@@ -84,7 +91,13 @@ void PlayerDemoWindow::startPlay(const QString& url)
 
     // 设置回调
     m_puller->setVideoRenderCallback([this](AVFrame* frame) {
+        static bool firstFrame = true;
+        if (firstFrame) {
+            m_videoWidget->Open(frame->width, frame->height);
+            firstFrame = false;
+        }
         m_videoWidget->Render(frame);
+
         updateProgress(); // 每次渲染视频帧时刷新进度条
     });
     m_puller->setAudioPlayCallback([this](AVFrame* frame) {

+ 3 - 0
AvPlayer/playerdemowindow.h

@@ -10,6 +10,7 @@
 #include <QPushButton>
 #include <QSlider>
 #include <QWidget>
+#include <QCheckBox>
 #include "AvRecorder/ui/opengl_video_widget.h"
 #include "Avplayer/FFmpegVideoPuller.h"
 
@@ -65,6 +66,8 @@ private:
     SwrContext* m_swrCtx = nullptr;
     uint8_t* m_swrBuffer = nullptr;
     int m_swrBufferSize = 0;
+
+    QCheckBox* m_keepAspectCheck = nullptr;
 };
 
 #endif // PLAYERDEMOWINDOW_H

+ 19 - 15
AvRecorder/ui/opengl_video_widget.cpp

@@ -11,6 +11,7 @@ OpenGLVideoWidget::OpenGLVideoWidget(QWidget* parent)
     , m_frameFormat(0)
     , m_frameUpdated(false)
     , m_initialized(false)
+    , m_keepAspectRatio(true)
 {
     // 设置顶点坐标
     m_vertices[0] = -1.0f; m_vertices[1] = -1.0f;
@@ -122,33 +123,36 @@ void OpenGLVideoWidget::resizeGL(int width, int height)
 void OpenGLVideoWidget::paintGL()
 {
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-    
     QMutexLocker locker(&m_mutex);
-    
     if (!m_frameData || m_frameWidth <= 0 || m_frameHeight <= 0 || !m_frameUpdated)
         return;
-    
     // 绑定纹理并更新数据
     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);
-    
-    // 使用着色器程序
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_frameWidth, m_frameHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_frameData);
     m_program->bind();
-    
-    // 设置纹理单元
     m_program->setUniformValue("texture", 0);
-    
-    // 设置顶点和纹理坐标
     m_program->enableAttributeArray(0);
     m_program->enableAttributeArray(1);
     m_program->setAttributeArray(0, m_vertices, 2);
     m_program->setAttributeArray(1, m_texCoords, 2);
-    
-    // 绘制
+    // 保持比例
+    if (m_keepAspectRatio) {
+        QSize widgetSize = size();
+        double widgetRatio = double(widgetSize.width()) / widgetSize.height();
+        double videoRatio = double(m_frameWidth) / m_frameHeight;
+        int x = 0, y = 0, w = widgetSize.width(), h = widgetSize.height();
+        if (widgetRatio > videoRatio) {
+            w = int(h * videoRatio);
+            x = (widgetSize.width() - w) / 2;
+        } else {
+            h = int(w / videoRatio);
+            y = (widgetSize.height() - h) / 2;
+        }
+        glViewport(x, y, w, h);
+    } else {
+        glViewport(0, 0, width(), height());
+    }
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-    
-    // 清理
     m_program->disableAttributeArray(0);
     m_program->disableAttributeArray(1);
     m_program->release();

+ 5 - 0
AvRecorder/ui/opengl_video_widget.h

@@ -34,6 +34,9 @@ public:
     // 添加从 AVFrame 转换的方法
     bool convertFromAVFrame(AVFrame* frame);
 
+    void setKeepAspectRatio(bool keep) { m_keepAspectRatio = keep; update(); }
+    bool keepAspectRatio() const { return m_keepAspectRatio; }
+
 protected:
     void initializeGL() override;
     void paintGL() override;
@@ -56,4 +59,6 @@ private:
     // 顶点和纹理坐标
     GLfloat m_vertices[8];
     GLfloat m_texCoords[8];
+
+    bool m_keepAspectRatio = true;
 };