From 33cf0cb360b1badb50cd3171c25afe913e383a04 Mon Sep 17 00:00:00 2001
From: cbwu <504-wuchengbo@htsdfp.com>
Date: Wed, 9 Oct 2024 15:35:20 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=90=8A=E8=88=B1?=
 =?UTF-8?q?=E6=8B=89=E6=B5=81=E5=9C=B0=E5=9D=80=E7=94=9F=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 PayloadAPP.pro                 |  2 +-
 Src/GDDC/gddcSet.cpp           | 61 ++++++++++++++++++++++++++--------
 Src/GDDC/gddcSet.h             | 11 +++---
 Src/GDDC/gddcSet.ui            | 45 +++++++++++++++++++------
 Src/GDDC/gddcdlg.cpp           |  7 ++++
 Src/GDDC/gddcdlg.h             |  4 +--
 Src/Video/ffmpegpushstream.cpp |  3 +-
 global.cpp                     | 39 +++++++++++++++++++++-
 global.h                       | 23 +++++++++++--
 mainwindow.cpp                 |  1 +
 10 files changed, 158 insertions(+), 38 deletions(-)

diff --git a/PayloadAPP.pro b/PayloadAPP.pro
index e5fa8f6..f6f245c 100644
--- a/PayloadAPP.pro
+++ b/PayloadAPP.pro
@@ -14,7 +14,7 @@ QMAKE_PROJECT_DEPTH = 0
 # QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'requireAdministrator\' uiAccess=\'false\'\"
 
 #程序版本
-VERSION = 1.0.0.1219
+VERSION = 1.0.0.1009
 #程序版本
 QMAKE_TARGET_COMPANY = "HTSDFP"
 
diff --git a/Src/GDDC/gddcSet.cpp b/Src/GDDC/gddcSet.cpp
index 798d5b9..c274131 100644
--- a/Src/GDDC/gddcSet.cpp
+++ b/Src/GDDC/gddcSet.cpp
@@ -37,15 +37,17 @@ void GDDCSet::initParam() {
   // ui->comboBox_streamType->addItem("UDP Raw");
   // ui->comboBox_streamType->addItem("UDP 422");
   // ui->comboBox_streamType->addItem("UDP TS");
-  ui->comboBox_playURL1->addItem("rtsp://192.168.55.65:554/live/track0");
+  ui->comboBox_playURL1->addItem(
+      QStringLiteral("rtsp://192.168.55.65:554/live/track0"));
+  ui->comboBox_playURL1->setCurrentIndex(0);
   // ui->comboBox_playURL1->addItem(
   //     "rtmp://liteavapp.qcloud.com/live/liteavdemoplayerstreamid");
   ui->comboBox_playURL1->setEditable(true);
+  ui->comboBox_streamSource->addItem("地面端");
+  ui->comboBox_streamSource->addItem("载荷端");
+  ui->comboBox_streamSource->setCurrentIndex(0);
 
-  ui->lineEdit_pushURL->setText(
-      QStringLiteral("rtmp://182.92.130.23/app/stream99"));
-  /*"rtsp://192.168.1.160:554/live/track0"*/
-  /*"rtmp://liteavapp.qcloud.com/live/liteavdemoplayerstreamid"*/
+  ui->lineEdit_pushURL->setText(QStringLiteral("-1"));
 
   ui->radioButton_NetCtrlUDP->setChecked(true);
   ui->radioButton_NetCtrlTCP->setChecked(false);
@@ -62,10 +64,10 @@ void GDDCSet::initParam() {
   m_FlowType = streamTypeToflowType(QString::fromUtf8(inBuf));
   ui->comboBox_streamType->setCurrentText(flowTypeTostreamType(m_FlowType));
 
-  ::GetPrivateProfileStringA("光电吊舱-视频连接-显示窗口1", "播放URL", "-1",
-                             inBuf, 100, strSysIniName);
-  m_playURL1 = QString::fromUtf8(inBuf);
-  ui->comboBox_playURL1->setCurrentText(m_playURL1);
+  // ::GetPrivateProfileStringA("光电吊舱-视频连接-显示窗口1", "播放URL", "-1",
+  //                            inBuf, 100, strSysIniName);
+  // m_playURL1 = QString::fromUtf8(inBuf);
+  // ui->comboBox_playURL1->setCurrentText(m_playURL1);
 
   // ::GetPrivateProfileStringA("光电吊舱-视频连接-显示窗口2", "播放URL", "-1",
   //                            inBuf, 100, strSysIniName);
@@ -75,7 +77,7 @@ void GDDCSet::initParam() {
   ::GetPrivateProfileStringA("光电吊舱-推流", "推流URL", "-1", inBuf, 100,
                              strSysIniName);
   m_pushURL = QString::fromUtf8(inBuf);
-  ui->lineEdit_pushURL->setText(m_pushURL);
+  // ui->lineEdit_pushURL->setText(m_pushURL);
 
   ::GetPrivateProfileStringA("光电吊舱-网络控制", "远端IP", "-1", inBuf, 100,
                              strSysIniName);
@@ -106,6 +108,7 @@ void GDDCSet::on_pushButton_ConnectURL1_clicked() {
     emit SignalStopConnect(1);
     ui->pushButton_ConnectURL1->setText("连接");
   }
+  // this->on_pushButton_pushURL_clicked();
 }
 
 // 视频连接-显示窗口2-连接
@@ -146,7 +149,6 @@ void GDDCSet::on_pushButton_NetCtrlConnect_clicked() {
     } else {
       emit SignalStartConnect(5);
     }
-
     ui->pushButton_NetCtrlConnect->setText("断开");
   } else {
     emit SignalStopConnect(4);
@@ -226,6 +228,13 @@ void GDDCSet::saveDataToLocalIni() {
   m_playURL1 = ui->comboBox_playURL1->currentText();
 }
 
+void GDDCSet::initPullURL(QString remoteIP) {
+  if (!remoteIP.isEmpty()) {
+    m_playURL1 = "rtsp://" + remoteIP + ":554/live/track0";
+  }
+  ui->comboBox_playURL1->setCurrentText(m_playURL1);
+}
+
 // //流类型
 // void GDDCSet::on_comboBox_streamType_currentIndexChanged(int index)
 // {
@@ -276,12 +285,36 @@ void GDDCSet::setPushStreamText(QString param) {
 
 // uavID值改变事件
 void GDDCSet::on_uavIDSpinBox_valueChanged(int arg1) {
+  QString streamSource = ui->comboBox_streamSource->currentText();
   int uavID = arg1;
   auto iter = g_mapAppName.find(uavID);
   if (iter != g_mapAppName.end()) {
-    QString pushURL =
-        generatePushURL(uavID, QString::fromStdString(iter->second));
-    ui->lineEdit_pushURL->setText(pushURL);
+    if ("地面端" == streamSource) {
+      QString pushURL =
+          generatePushURL(uavID, QString::fromStdString(iter->second));
+      ui->lineEdit_pushURL->setText(pushURL);
+    } else {
+      QString pullURL =
+          generatePullURL(uavID, QString::fromStdString(iter->second));
+      ui->comboBox_playURL1->setItemText(0, pullURL);
+    }
   } else {
   }
 }
+
+// 切换拉流来源
+void GDDCSet::on_comboBox_streamSource_currentIndexChanged(int index) {
+  if (0 == index) {
+    ui->pushButton_pushURL->setEnabled(true);
+    ui->comboBox_playURL1->setItemText(0, m_playURL1);
+  } else if (1 == index) {
+    ui->pushButton_pushURL->setEnabled(false);
+    int uavID = ui->uavIDSpinBox->value();
+    auto iter = g_mapAppName.find(uavID);
+    if (iter != g_mapAppName.end()) {
+      QString pullURL =
+          generatePullURL(uavID, QString::fromStdString(iter->second));
+      ui->comboBox_playURL1->setItemText(0, pullURL);
+    }
+  }
+}
diff --git a/Src/GDDC/gddcSet.h b/Src/GDDC/gddcSet.h
index ae15381..32cd274 100644
--- a/Src/GDDC/gddcSet.h
+++ b/Src/GDDC/gddcSet.h
@@ -23,10 +23,11 @@ private:
   Ui::GDDCSet *ui;
 
 public:
-  void initUDPSocket();       // 初始化UDPSocket
-  void initWindow();          // 初始化窗口
-  void initParam();           // 初始化参数
-  void saveDataToLocalIni();  // 保存数据至本地ini文件
+  void initUDPSocket();      // 初始化UDPSocket
+  void initWindow();         // 初始化窗口
+  void initParam();          // 初始化参数
+  void saveDataToLocalIni(); // 保存数据至本地ini文件
+  void initPullURL(QString remoteIP);
   QByteArray m_configIniPath; // ini配置文件路径
 
   QString m_playURL1; // 光电吊舱-视频连接-显示窗口1-URL地址
@@ -34,7 +35,6 @@ public:
   QString m_pushURL;  // 光电吊舱-推流URL地址
   MyPairNetwork m_myPairNetwork; // 网络通信结构体
   QString m_FlowType;            // 流类型
-
   QString streamTypeToflowType(QString);
   QString flowTypeTostreamType(QString);
 
@@ -63,6 +63,7 @@ private slots:
   void on_pushButton_pushURL_clicked();              // 推流
   // void on_comboBox_streamType_currentIndexChanged(int index);
   void on_uavIDSpinBox_valueChanged(int arg1);
+  void on_comboBox_streamSource_currentIndexChanged(int index);
 };
 
 #endif // GDDCSET_H
diff --git a/Src/GDDC/gddcSet.ui b/Src/GDDC/gddcSet.ui
index 41370a4..580238b 100644
--- a/Src/GDDC/gddcSet.ui
+++ b/Src/GDDC/gddcSet.ui
@@ -29,14 +29,14 @@
     <string>视频连接</string>
    </property>
    <property name="alignment">
-    <set>Qt::AlignmentFlag::AlignCenter</set>
+    <set>Qt::AlignCenter</set>
    </property>
    <widget class="QLabel" name="label_3">
     <property name="geometry">
      <rect>
-      <x>500</x>
+      <x>510</x>
       <y>60</y>
-      <width>61</width>
+      <width>51</width>
       <height>21</height>
      </rect>
     </property>
@@ -85,7 +85,7 @@
      <rect>
       <x>80</x>
       <y>60</y>
-      <width>411</width>
+      <width>301</width>
       <height>23</height>
      </rect>
     </property>
@@ -194,7 +194,7 @@
    <widget class="QLabel" name="label_15">
     <property name="geometry">
      <rect>
-      <x>500</x>
+      <x>510</x>
       <y>100</y>
       <width>61</width>
       <height>21</height>
@@ -207,20 +207,43 @@
    <widget class="QSpinBox" name="uavIDSpinBox">
     <property name="geometry">
      <rect>
-      <x>560</x>
+      <x>570</x>
       <y>100</y>
-      <width>61</width>
+      <width>51</width>
       <height>23</height>
      </rect>
     </property>
     <property name="buttonSymbols">
-     <enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
+     <enum>QAbstractSpinBox::NoButtons</enum>
     </property>
     <property name="maximum">
      <number>255</number>
     </property>
     <property name="stepType">
-     <enum>QAbstractSpinBox::StepType::DefaultStepType</enum>
+     <enum>QAbstractSpinBox::DefaultStepType</enum>
+    </property>
+   </widget>
+   <widget class="QLabel" name="label_16">
+    <property name="geometry">
+     <rect>
+      <x>390</x>
+      <y>60</y>
+      <width>51</width>
+      <height>21</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>流来源:</string>
+    </property>
+   </widget>
+   <widget class="QComboBox" name="comboBox_streamSource">
+    <property name="geometry">
+     <rect>
+      <x>440</x>
+      <y>60</y>
+      <width>61</width>
+      <height>23</height>
+     </rect>
     </property>
    </widget>
   </widget>
@@ -237,7 +260,7 @@
     <string>串口控制</string>
    </property>
    <property name="alignment">
-    <set>Qt::AlignmentFlag::AlignCenter</set>
+    <set>Qt::AlignCenter</set>
    </property>
    <widget class="QPushButton" name="pushButton_serialControlConnect">
     <property name="geometry">
@@ -325,7 +348,7 @@
     <string>网络控制</string>
    </property>
    <property name="alignment">
-    <set>Qt::AlignmentFlag::AlignCenter</set>
+    <set>Qt::AlignCenter</set>
    </property>
    <widget class="QPushButton" name="pushButton_NetCtrlConnect">
     <property name="geometry">
diff --git a/Src/GDDC/gddcdlg.cpp b/Src/GDDC/gddcdlg.cpp
index 581ac04..2ac1ee3 100644
--- a/Src/GDDC/gddcdlg.cpp
+++ b/Src/GDDC/gddcdlg.cpp
@@ -339,6 +339,13 @@ void GDDCdlg::resizeUI() {
   ui->pushButShowStatePage->raise();
 }
 
+void GDDCdlg::setGlobalSetMap(
+    std::unordered_map<QString, settingStruct> &gSetMap) {
+  if (m_DlgGDDCSet) {
+    m_DlgGDDCSet->initPullURL(gSetMap["光电吊舱"].net.remoteIp);
+  }
+}
+
 // 定时器处理
 void GDDCdlg::GDDCControlTimeOut() {
   if (m_GDDCCmdDlg->sendTimes > 0) { // 优先发送次数指令
diff --git a/Src/GDDC/gddcdlg.h b/Src/GDDC/gddcdlg.h
index c8139f0..07e5fe5 100644
--- a/Src/GDDC/gddcdlg.h
+++ b/Src/GDDC/gddcdlg.h
@@ -22,8 +22,8 @@
 // #include "ui_gddcStateInfo.h"   //吊舱状态信息显示对话框
 // #include "ui_gddcSet.h"
 #include "QProcess"
-#include <QThread>
 #include <QMessageBox>
+#include <QThread>
 
 #define cmdLength 44
 namespace Ui {
@@ -49,6 +49,7 @@ public:
   void initParam();      // 初始化参数
   void initSignalSlot(); // 初始化信号与槽
   void resizeUI();       // 重新设置布局
+  void setGlobalSetMap(std::unordered_map<QString, settingStruct> &gSetMap);
 
   GDDCSet *m_DlgGDDCSet;         // 光电吊舱设置对话框
   GDDCCmdDlg *m_GDDCCmdDlg;      // 光电吊舱控制对话框
@@ -64,7 +65,6 @@ public:
   quint16 localPort;      // 本地port
   QProcess *process;      // 执行CMD
   QThread workerThread;   // 线程
-
   // bool eventFilter(QObject *,QEvent *);          //事件过滤器
   void mousePressEvent(QMouseEvent *event); // 事件过滤器
   void mouseMoveEvent(QMouseEvent *event);  // 事件过滤器
diff --git a/Src/Video/ffmpegpushstream.cpp b/Src/Video/ffmpegpushstream.cpp
index 24079f9..a8e7031 100644
--- a/Src/Video/ffmpegpushstream.cpp
+++ b/Src/Video/ffmpegpushstream.cpp
@@ -155,7 +155,8 @@ int FFmpegPushStream::pushStream(AVPacket *pkt, int frm_cnt, int64_t startTime,
  * @brief 停止推流
  */
 void FFmpegPushStream::stopPush() {
-  av_write_trailer(outputFormatCtx);
+  if (mInitStatus)
+    av_write_trailer(outputFormatCtx);
   // 关闭输出
   if (outputFormatCtx && !(outputFormatCtx->flags & AVFMT_NOFILE)) {
     avio_close(outputFormatCtx->pb);
diff --git a/global.cpp b/global.cpp
index 954e3bf..8c363cc 100644
--- a/global.cpp
+++ b/global.cpp
@@ -2,7 +2,7 @@
 
 global::global() {}
 
-QString g_SoftwareVersion = "版本号:V1.0.0.0919";
+QString g_SoftwareVersion = "版本号:V1.0.0.1009";
 
 QColor g_themeColor(51, 51, 51);
 QString g_PushBtnStyle = /**正常情况下样式**/
@@ -203,3 +203,40 @@ QString generatePushURL(int uavID, QString appName, QString uavName,
 }
 
 std::map<int, std::string> g_mapAppName;
+
+/**
+ * @brief 生成拉流地址
+ * @param uavID: 飞控ID
+ * @param appName: app名称
+ * @param uavName: 飞机型号,默认981cs
+ * @param clientID: 数据推流端ID,0为地面端,1为载荷端。
+ * @param pullDomain: 拉流域名
+ * @param expireTime: 过期时间(单位是秒),默认1h。
+ * @param pullKey: 拉流域名配置的鉴权Key
+ * @return 返回拉流地址
+ */
+QString generatePullURL(int uavID, QString appName, QString uavName,
+                        int clientID, QString pullDomain, long expireTime,
+                        QString pullKey) {
+  QString rtmpUrl = "";
+  QString clientName = "";
+  if (0 == clientID) {
+    clientName = "gcs"; // 地面端
+  } else {
+    clientName = "uav"; // 载荷端
+  }
+  QString streamName =
+      uavName + "_" + QString::number(uavID) + "_" + clientName;
+  if (pullKey == "") {
+    rtmpUrl = "rtmp://" + pullDomain + "/" + appName + "/" + streamName;
+  } else {
+    // 计算鉴权串
+    long timeStamp = QDateTime::currentMSecsSinceEpoch() / 1000 + expireTime;
+    QString stringToMd5 = "/" + appName + "/" + streamName + "-" +
+                          QString::number(timeStamp) + "-0-0-" + pullKey;
+    QString authKey = calculateMD5(stringToMd5);
+    rtmpUrl = "rtmp://" + pullDomain + "/" + appName + "/" + streamName +
+              "?auth_key=" + QString::number(timeStamp) + "-0-0-" + authKey;
+  }
+  return rtmpUrl;
+}
diff --git a/global.h b/global.h
index 918cd6a..78eee34 100644
--- a/global.h
+++ b/global.h
@@ -37,7 +37,7 @@ extern QString calculateMD5(const QString &str);
  * @param uavName: 飞机型号,默认981cs
  * @param clientID: 客户端ID,0为地面端,1为载荷端。
  * @param pushDomain: 推流域名
- * @param appName: app名称
+ * @param appName
  * @param expireTime: 过期时间(单位是秒),默认1h。
  * @param pushKey: 推流域名配置的鉴权Key
  * @return 返回推流地址
@@ -45,8 +45,25 @@ extern QString calculateMD5(const QString &str);
 extern QString generatePushURL(int uavID, QString appName = "nmyj",
                                QString uavName = "981cs", int clientID = 0,
                                QString pushDomain = "push.htsdfp.com",
-                               long expireTime = 4 * 3600,
-                               QString pushKey = "2G2Fu4MXO9D9Hrs7");
+                               long expireTime = 6 * 3600,
+                               QString pushKey = "ZRjGVcPYGhKib0rdgH");
+
+/**
+ * @brief 生成拉流地址
+ * @param uavID: 飞控ID
+ * @param appName: app名称
+ * @param uavName: 飞机型号,默认981cs
+ * @param clientID: 数据推流端ID,0为地面端,1为载荷端。
+ * @param pullDomain: 拉流域名
+ * @param expireTime: 过期时间(单位是秒),默认1h。
+ * @param pullKey: 拉流域名配置的鉴权Key
+ * @return 返回拉流地址
+ */
+extern QString generatePullURL(int uavID, QString appName = "nmyj",
+                               QString uavName = "981cs", int clientID = 1,
+                               QString pullDomain = "play.htsdfp.com",
+                               long expireTime = 6 * 3600,
+                               QString pullKey = "HDaMVkLnIcr0mGhV8d");
 
 extern std::map<int, std::string> g_mapAppName;
 
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 357f778..5fd039a 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -84,6 +84,7 @@ void MainWindow::initWindow() {
 
   // 使用类中的get方法获取配置文件中的IP
   m_allSetMap = m_HomePagedlg->settingWidget->getAllParam();
+  m_GDDCdlg->setGlobalSetMap(m_allSetMap);
   qDebug() << "=============设备配置================";
   qDebug() << "光电吊舱------";
   qDebug() << "远端ip" << m_allSetMap["光电吊舱"].net.remoteIp;