فهرست منبع

修复: 项目的未知异常

zhuizhu 7 ماه پیش
والد
کامیت
66f62fe51f
3فایلهای تغییر یافته به همراه91 افزوده شده و 10 حذف شده
  1. 21 6
      AvRecorder/ui/av_recorder.cpp
  2. 63 4
      AvRecorder/ui/settings_page.cpp
  3. 7 0
      AvRecorder/ui/settings_page.h

+ 21 - 6
AvRecorder/ui/av_recorder.cpp

@@ -2,8 +2,10 @@
 
 #include <QDateTime>
 #include <QStatusBar>
-#include <capturer/finder.h>
+#include <QMessageBox>
 #include "avrecorder/capturer/video/VideoCaptureManager.h"
+#include "qglobal.h"
+#include <capturer/finder.h>
 using namespace avrecorder::video;
 
 AvRecorder::AvRecorder(QWidget* parent)
@@ -21,8 +23,8 @@ AvRecorder::AvRecorder(QWidget* parent)
         m_settingsParam.audioParam.name = aencs.empty() ? std::string("aac") : aencs.front();
     }
     // 设置安全的默认分辨率,避免在捕获首帧前width/height为0
-    m_settingsParam.videoParam.width = 1280;
-    m_settingsParam.videoParam.height = 720;
+    m_settingsParam.videoParam.width = 1920;
+    m_settingsParam.videoParam.height = 1080;
     m_settingsParam.outputDir = ".";
     m_settingsParam.liveUrl = "rtmp://127.0.0.1:1935/stream/V1";
     m_settingsParam.liveName = "stream";
@@ -133,8 +135,8 @@ void AvRecorder::setSettings(const SettingsPage::Param& param)
         m_settingsParam.audioParam.name = aencs.empty() ? std::string("aac") : aencs.front();
     }
     // 重置时也保持安全默认分辨率,实际分辨率会在捕获后更新
-    m_settingsParam.videoParam.width = 1280;
-    m_settingsParam.videoParam.height = 720;
+    m_settingsParam.videoParam.width = 1920;
+    m_settingsParam.videoParam.height = 1080;
     m_settingsParam.outputDir = ".";
     m_settingsParam.liveUrl = param.liveUrl;   // "rtmp://192.168.3.76:1935/stream/V1";
     m_settingsParam.liveName = param.liveName; // "stream";
@@ -184,6 +186,8 @@ void AvRecorder::initConnect()
 
             m_recordBtn->setEnabled(false);
             m_liveBtn->setText("停止直播");
+            // 显式设置直播状态
+            m_isLive = true;
         } else {
             // 先停止同步录像
             stopSyncRecord();
@@ -191,6 +195,8 @@ void AvRecorder::initConnect()
             stopStream();
             m_recordBtn->setEnabled(true);
             m_liveBtn->setText("开始直播");
+            // 显式清除直播状态
+            m_isLive = false;
         }
     });
     connect(m_microphoneWidget, &AudioWidget::SetVolumeScale, this, [this](float scale) {
@@ -233,6 +239,11 @@ void AvRecorder::initConnect()
         startPreview();
     });
     connect(m_settingsBtn, &QPushButton::released, this, [this] {
+        // 运行中禁止打开设置以切换编码器,避免异常
+        if (m_isRecord || m_isLive || m_isSyncRecord) {
+            QMessageBox::warning(this, "提示", "正在直播/录制,无法修改编码器设置。请先停止后再修改。");
+            return;
+        }
         auto settingsPage = std::make_unique<SettingsPage>(&m_settingsParam, this);
         settingsPage->exec();
         m_isLocked = true;
@@ -366,6 +377,10 @@ void AvRecorder::stopCapture()
 void AvRecorder::renderFrame()
 {
     auto frame = m_videoRecorder.GetRenderFrame();
+    if (!frame) {
+        qDebug() << "renderFrame error";
+        return;
+    }
     AVFrame* copiedFrame = av_frame_clone(frame);
     // m_glWidget->Render(copiedFrame);
     QMetaObject::invokeMethod(m_glWidget,
@@ -456,7 +471,7 @@ bool AvRecorder::startStream(std::string_view path, std::string_view format)
     m_updateListBtn->setEnabled(false);
     m_captureMethodBox->setEnabled(false); // 禁用采集方式切换
 
-    m_isLive = !m_isLive;
+    // 注意:不要在这里修改 m_isLive,由调用方(按钮逻辑)根据场景设置
     return true;
 }
 

+ 63 - 4
AvRecorder/ui/settings_page.cpp

@@ -34,6 +34,12 @@ void SettingsPage::_InitConnect()
             _fileDirEdit->setText(selectedDir);
         }
     });
+
+    if (_resetBestBtn) {
+        connect(_resetBestBtn, &QPushButton::released, [this] {
+            _ApplyBestDefaults();
+        });
+    }
 }
 
 void SettingsPage::_WriteSettings()
@@ -41,13 +47,16 @@ void SettingsPage::_WriteSettings()
     _param->videoParam.bitRate = _videoBitRateBox->value() * 1000;
     _param->videoParam.fps = _videoFpsBox->value();
     _param->videoParam.name = _videoEncoderBox->currentText().toStdString();
+    _param->videoParam.width = _videoWidthBox ? _videoWidthBox->value() : _param->videoParam.width;
+    _param->videoParam.height = _videoHeightBox ? _videoHeightBox->value() : _param->videoParam.height;
+
     _param->audioParam.bitRate = _audioBitRateBox->value() * 1000;
     if (_audioEncoderBox) {
         _param->audioParam.name = _audioEncoderBox->currentText().toStdString();
     }
+
     _param->outputDir = _fileDirEdit->text().toStdString();
-    // _param->liveUrl = _liveUrlEdit->text().toStdString();
-    // _param->liveName = _liveNameEdit->text().toStdString();
+    // 直播参数为项目内置设置,不从UI写回
 }
 
 void SettingsPage::_InitUi()
@@ -57,11 +66,15 @@ void SettingsPage::_InitUi()
     layout->addWidget(_InitVideoUi());
     layout->addWidget(_InitAudioUi());
     layout->addWidget(_InitOutputUi());
+    // 不显示“直播”设置(项目内置配置,不需要在UI中展示)
     auto hLayout = new QHBoxLayout;
+    _resetBestBtn = new QPushButton("最佳默认");
     _applyBtn = new QPushButton("应用");
     _cancelBtn = new QPushButton("取消");
     _yesBtn = new QPushButton("确定");
     hLayout->setAlignment(Qt::AlignRight);
+    hLayout->addWidget(_resetBestBtn);
+    hLayout->addStretch();
     hLayout->addWidget(_applyBtn);
     hLayout->addWidget(_cancelBtn);
     hLayout->addWidget(_yesBtn);
@@ -78,9 +91,20 @@ QGroupBox* SettingsPage::_InitVideoUi()
     _videoBitRateBox->setMaximum(INT_MAX);
     _videoBitRateBox->setValue(_param->videoParam.bitRate / 1000);
     _videoFpsBox = new QSpinBox;
-    _videoFpsBox->setMinimum(0);
-    _videoFpsBox->setMaximum(60);
+    _videoFpsBox->setMinimum(1);
+    _videoFpsBox->setMaximum(120);
     _videoFpsBox->setValue(_param->videoParam.fps);
+
+    // 分辨率设置
+    _videoWidthBox = new QSpinBox;
+    _videoWidthBox->setMinimum(160);
+    _videoWidthBox->setMaximum(7680);
+    _videoWidthBox->setValue(_param->videoParam.width > 0 ? _param->videoParam.width : 1920);
+    _videoHeightBox = new QSpinBox;
+    _videoHeightBox->setMinimum(120);
+    _videoHeightBox->setMaximum(4320);
+    _videoHeightBox->setValue(_param->videoParam.height > 0 ? _param->videoParam.height : 1080);
+
     _videoEncoderBox = new QComboBox;
     auto&& encoders = Encoder<MediaType::VIDEO>::GetUsableEncoders();
     for (auto&& encoder : encoders) {
@@ -99,6 +123,10 @@ QGroupBox* SettingsPage::_InitVideoUi()
         _CreateDescription("比特率(kB):", "越高的比特率越清晰, 但越占用硬件资源", _videoBitRateBox));
     layout->addLayout(
         _CreateDescription("帧率:", "越高的帧率越流畅, 但越占用硬件资源", _videoFpsBox));
+    layout->addLayout(
+        _CreateDescription("分辨率-宽:", "输出视频宽度,建议与屏幕或窗口比例一致", _videoWidthBox));
+    layout->addLayout(
+        _CreateDescription("分辨率-高:", "输出视频高度,建议与屏幕或窗口比例一致", _videoHeightBox));
     layout->addLayout(_CreateDescription(
         "编码器:",
         "libx264 为软件编码, CPU占用高但兼容性强, 其他为硬件编码, 效果与软件编码相反",
@@ -154,6 +182,37 @@ QGroupBox* SettingsPage::_InitOutputUi()
     return groupBox;
 }
 
+QGroupBox* SettingsPage::_InitLiveUi()
+{
+    auto groupBox = new QGroupBox("直播");
+    auto layout = new QVBoxLayout;
+    _liveUrlEdit = new QLineEdit(QString::fromStdString(_param->liveUrl));
+    _liveNameEdit = new QLineEdit(QString::fromStdString(_param->liveName));
+    layout->addLayout(_CreateDescription("推流地址:", "例如: rtmp://<server>:1935/stream/V1 或 rtsp://...", _liveUrlEdit));
+    layout->addLayout(_CreateDescription("流名称:", "推流路径中的名称或Key", _liveNameEdit));
+    groupBox->setLayout(layout);
+    return groupBox;
+}
+
+void SettingsPage::_ApplyBestDefaults()
+{
+    // 优先选择可用编码器列表的第一项(通常为硬件加速编码器)
+    if (_videoEncoderBox && _videoEncoderBox->count() > 0) {
+        _videoEncoderBox->setCurrentIndex(0);
+    }
+    if (_audioEncoderBox && _audioEncoderBox->count() > 0) {
+        _audioEncoderBox->setCurrentIndex(0);
+    }
+
+    // 设置为通用的高质量方案:1080p@30fps, 8 Mbps;音频 160 kbps
+    if (_videoWidthBox) _videoWidthBox->setValue(1920);
+    if (_videoHeightBox) _videoHeightBox->setValue(1080);
+    if (_videoFpsBox) _videoFpsBox->setValue(30);
+    if (_videoBitRateBox) _videoBitRateBox->setValue(8000);
+
+    if (_audioBitRateBox) _audioBitRateBox->setValue(160);
+}
+
 QHBoxLayout* SettingsPage::_CreateDescription(std::string_view text,
                                               std::string_view textEx,
                                               QWidget* widget)

+ 7 - 0
AvRecorder/ui/settings_page.h

@@ -30,17 +30,24 @@ private:
     QGroupBox* _InitVideoUi();
     QGroupBox* _InitAudioUi();
     QGroupBox* _InitOutputUi();
+    QGroupBox* _InitLiveUi();
+    void _ApplyBestDefaults();
     Param* _param = nullptr;
     QSpinBox* _videoBitRateBox = nullptr;
     QSpinBox* _videoFpsBox = nullptr;
     QComboBox* _videoEncoderBox = nullptr;
+    QSpinBox* _videoWidthBox = nullptr;
+    QSpinBox* _videoHeightBox = nullptr;
     QSpinBox* _audioBitRateBox = nullptr;
     QComboBox* _audioEncoderBox = nullptr;
     QLineEdit* _fileDirEdit = nullptr;
+    QLineEdit* _liveUrlEdit = nullptr;
+    QLineEdit* _liveNameEdit = nullptr;
     QPushButton* _selDirBtn = nullptr;
     QPushButton* _applyBtn = nullptr;
     QPushButton* _cancelBtn = nullptr;
     QPushButton* _yesBtn = nullptr;
+    QPushButton* _resetBestBtn = nullptr;
 
     QHBoxLayout* _CreateDescription(std::string_view text, std::string_view textEx, QWidget* widget);
 };