Ver código fonte

V1.2.3
1、修复了内存泄漏的bug

Apple 3 semanas atrás
pai
commit
25011f8b58

+ 1 - 1
CMakeLists.txt

@@ -193,7 +193,7 @@ file(GLOB GLOBAL_SRC
 
 if(CMAKE_SYSTEM_NAME MATCHES "Linux")
 add_subdirectory(${CMAKE_SOURCE_DIR}/Server)
-# add_subdirectory(${CMAKE_SOURCE_DIR}/show3)
+add_subdirectory(${CMAKE_SOURCE_DIR}/show3)
 endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
 
 

+ 7 - 0
SQL/ACAServer.sql

@@ -134,6 +134,13 @@ INSERT INTO tACASoundCardPCMChannels (
 );
 
 
+#更新报警文件状态信息
+UPDATE tACAAlarmInfo
+SET FileState = @fileState
+WHERE PKID = @pkid;
+
+
+
 #删除PCM通道信息
 DELETE FROM tACASoundCardPCMChannels
 WHERE PKID = @pkid;

+ 3 - 0
Server/DataStruct/AudioData.h

@@ -5,6 +5,7 @@
 #include <QDateTime>
 #include <qdatetime.h>
 #include <vector>
+#include <QVector>
 
 #include "GlobalVariable.h"
 #include "CalculateAudio.h"
@@ -209,6 +210,8 @@ struct AudioLeftRightData
     /* 音频数据 */
     std::vector<double> vecLeftData;        /* 左声道数据 */
     std::vector<double> vecRightData;       /* 右声道数据 */
+    // QVector<double> vecLeftData;        /* 左声道数据 */
+    // QVector<double> vecRightData;       /* 右声道数据 */
     int totalSize = 0;                      /* 总长度,两个声道的总长度是一样的 */
     int numMSecond = 0;                     /* 数据对应的毫秒数 */
     QDateTime startTime;                    /* 开始时间戳 */

+ 11 - 10
Server/ThreadCalculate/CompareItemThread.cpp

@@ -42,6 +42,7 @@ void CompareItemThread::thread_task()
     SPDLOG_LOGGER_INFO(m_logger, "----------------------------------------------------------------");
 
     /* --------------------------- 这里模拟线程运行 --------------------------- */
+#if CI_SIMULATE
     m_isRunning.store(true);
     /* 创建录音通道线程 */
     for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
@@ -65,6 +66,7 @@ void CompareItemThread::thread_task()
     m_isStoped.store(true);
     return;
 
+#endif /* CI_SIMULATE */
     /* --------------------------------------------------------------------------------- */
 
 
@@ -72,11 +74,15 @@ void CompareItemThread::thread_task()
     if(!initData())
     {
         SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase);
+        clearData();
+        m_threadInfo.threadState.store(EThreadState::State_Error);
+        m_isRunning.store(false);
+        m_isStoped.store(true);
         return;
     }
     
     /* 更新线程状态标志 */
-    m_threadInfo.threadState = EThreadState::State_Running;
+    m_threadInfo.threadState.store(EThreadState::State_Running);
     m_isStoped = false;
 
 
@@ -118,7 +124,7 @@ void CompareItemThread::thread_task()
     }
 
     SPDLOG_LOGGER_WARN(m_logger, "★ {} 线程结束运行", m_logBase);
-    m_threadInfo.threadState = EThreadState::State_Stopped;
+    m_threadInfo.threadState.store(EThreadState::State_Stopped);
     m_isStoped = true;
 }
 
@@ -234,8 +240,6 @@ bool CompareItemThread::initData()
     /* 一致性对比的一些参数 */
     const auto& aiCompareConfig = SysConfig.getAICompareConfig();
     m_isConsistencyNoWarnWhenOtherAlarm = aiCompareConfig.bNoConsistencyAlarmOtherAlarm;
-    // m_isNotConsistencyOneRoadNoise = (baseConfig.nNotConsistency == 2);
-    // m_isNotConsistencyIgnoreSilent = (baseConfig.nNotConsistency == 3);
 
     /* 创建录音通道线程 */
     for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
@@ -244,17 +248,14 @@ bool CompareItemThread::initData()
     }
 
     /* 创建计算音量报警信息的线程指针 */
-    // destroyCalculateDBThreads(); // 清理之前的线程
     createCalculateDBThreads();
 
     /* 创建两个对比线程,主通道是第一个通道,其他都需要和主通道进行对比 */
-    // destroyCompareThreads();
     createCompareThreads();
 
     /* 创建计算噪音的线程 */
     if(m_noiseDetectConfig.isEnableNoiseDetect)
     {
-        // destroyNoiseDetectThreads();
         createNoiseDetectThreads();
     }
     
@@ -478,7 +479,7 @@ bool CompareItemThread::createCompareThreads()
         compareThreadInfo.compareItemInfo.mapRoad.clear(); // 清空通道信息
         compareThreadInfo.compareItemInfo.mapRoad.insert(mainRoad.nCompareRoadNum, mainRoad);   // 添加主通道
         compareThreadInfo.compareItemInfo.mapRoad.insert(it.key(), it.value());                 // 添加当前通道
-        compareThreadInfo.threadState = EThreadState::State_Inited;
+        compareThreadInfo.threadState.store(EThreadState::State_Inited);
         ConsistencyCompareThread* pThread = new ConsistencyCompareThread(compareThreadInfo);
         if(pThread == nullptr)
         {
@@ -531,7 +532,7 @@ bool CompareItemThread::createCalculateDBThreads()
         threadInfo.compareItemInfo.paramOverload = m_threadInfo.compareItemInfo.paramOverload;
         threadInfo.compareItemInfo.paramPhase = m_threadInfo.compareItemInfo.paramPhase;
         /* 添加线程信息 */
-        threadInfo.threadState = EThreadState::State_Inited;
+        threadInfo.threadState.store(EThreadState::State_Inited);
         threadInfo.threadType = EThreadType::Type_CalculateDB;
         CalculateDBThread* pThread = new CalculateDBThread(threadInfo);
         if(pThread == nullptr)
@@ -588,7 +589,7 @@ void CompareItemThread::createNoiseDetectThreads()
         threadInfo.compareItemInfo.nID = m_threadInfo.compareItemInfo.nID;
         threadInfo.compareItemInfo.strName = m_threadInfo.compareItemInfo.strName;
         threadInfo.compareItemInfo.mapRoad.insert(road.nCompareRoadNum, road); // 添加当前通道
-        threadInfo.threadState = EThreadState::State_Inited; // 初始化线程状态
+        threadInfo.threadState.store(EThreadState::State_Inited); // 初始化线程状态
         threadInfo.threadType = EThreadType::Type_CalculateDB;
         NoiseDetectThread* pThread = new NoiseDetectThread(threadInfo);
         if(pThread == nullptr)

+ 3 - 0
Server/ThreadCalculate/CompareItemThread.h

@@ -21,6 +21,9 @@ class CreateRecordFileThread;
 class ConsistencyCompareThread;
 
 
+#define CI_SIMULATE false
+
+
 /**
     对比项功能线程
         功能:

+ 9 - 5
Server/ThreadManager/ThreadCompareItemManager.cpp

@@ -315,7 +315,7 @@ void ThreadCompareItemManager::checkCompareItemInfo(QList<CompareItemInfo_t>& ne
 
 /**
  * @brief 处理需要删除的对比项线程
- *        1、先处理已经停止的线程,理论上不会有这个内容了,在上次循环中已经处理过了
+ *        1、先处理已经停止的线程,初始化失败的对比项会设置错误状态
  *        2、再将这次列表中的对比项ID对应的线程设置为停止状态,待到下次循环再删除已经停止完成的线程
  * 
  * @param deleteList 
@@ -332,9 +332,11 @@ void ThreadCompareItemManager::processDeleteCompareItemThreads(const QList<int>&
             it = m_mapThreads.erase(it);
             continue;
         }
-        if(pThread->getThreadInfo().threadState == EThreadState::State_Stopped)
+        if(pThread->getThreadInfo().threadState == EThreadState::State_Stopped ||
+            pThread->getThreadInfo().threadState == EThreadState::State_Error )
         {
-            /* 线程已经停止,直接删除 */
+            /* 确保线程已经停止 */
+            pThread->thread_stop_block();
             SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 已经停止,准备删除", pThread->getThreadInfo().compareItemInfo.strName.toStdString());
             delete pThread;
             it = m_mapThreads.erase(it);
@@ -404,7 +406,7 @@ bool ThreadCompareItemManager::createNewCompareItemThreads(const QList<CompareIt
         CalculateThreadInfo_t threadInfo;
         threadInfo.compareItemInfo = it;
         threadInfo.threadType = EThreadType::Type_CompareItem;
-        threadInfo.threadState = EThreadState::State_Inited;
+        threadInfo.threadState.store(EThreadState::State_Inited);
 
         CPPTP.add_task(&ThreadCompareItemManager::thread_compareItem, threadInfo);
 
@@ -546,11 +548,13 @@ void ThreadCompareItemManager::updateCompareItemInfoToMQTT()
         }
     }
 
-    if(isUpdated)
+    /* 服务启动,可能对比项是空的,上面检查结果为false,但是也需要发送一次清空对比项 */
+    if(isUpdated || m_isOneSend.load())
     {
         sendCompareItemInfoToMQTT(newMap);
         m_mapMQTTItemInfo = newMap;
     }
+    m_isOneSend.store(false);
 }
 
 /* 发送到MQTT */

+ 1 - 0
Server/ThreadManager/ThreadCompareItemManager.h

@@ -106,6 +106,7 @@ private:
     QString m_webAPIAppType;                      /* WebAPI应用类型 */
 
     /* ---------------------- 对比项信息 ---------------------- */
+    std::atomic_bool m_isOneSend = true;        /* 开启服务先发送一次 */
     std::mutex m_mutexCompareItemThreads;       /* 对比项线程的互斥锁 */
     // QList<CompareItemInfo_t> m_listNewItems;    /* 对比项列表,从数据库获取到的新的列表 */
     QMap<int, CompareItemInfo_t> m_mapNowCompareItem; /* 当前的对比项信息,在检查是否有对比项更新的时候更新该值 */

+ 52 - 42
Server/ThreadManager/ThreadManager.cpp

@@ -38,6 +38,16 @@ void ThreadManager::stopAllThreads()
 
 }
 
+/* 线程函数,销毁录音线程 */
+void ThreadManager::thread_destroyeRecordThread()
+{
+    while(true)
+    {
+        std::this_thread::sleep_for(std::chrono::milliseconds(100));
+        destroyeRecordThread();
+    }
+}
+
 /* 创建一个录音通道及其附属的线程 */
 bool ThreadManager::createRecordThread(const OneSoundCardPCMInfo_t& pcmInfo, int compareItemID)
 {
@@ -76,52 +86,52 @@ bool ThreadManager::createRecordThread(const OneSoundCardPCMInfo_t& pcmInfo, int
     /* 先创建生成wav小文件数据的线程 */
     RecordThreadInfo_t threadInfo;
     threadInfo.cardRoadInfo = pcmInfo;
-    threadInfo.threadState = EThreadState::State_Inited;
+    threadInfo.threadState.store(EThreadState::State_Inited);
     threadInfo.threadType = EThreadType::Type_CreateWAV;
-    // CreateWAVThread* pCreateWAVThread = new CreateWAVThread(threadInfo);
-    // if(pCreateWAVThread == nullptr)
-    // {
-    //     SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建生成wav小文件线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
-    //     // return false; // 创建失败
-    // }else 
-    // {
-    //     CPPTP.add_task(&CreateWAVThread::thread_task, pCreateWAVThread);
-    //     std::lock_guard<std::mutex> lock(m_mutexCreateWAVThreads);
-    //     m_createWAVThreads.push_back(pCreateWAVThread);
-    // }
+    CreateWAVThread* pCreateWAVThread = new CreateWAVThread(threadInfo);
+    if(pCreateWAVThread == nullptr)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建生成wav小文件线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
+        // return false; // 创建失败
+    }else 
+    {
+        CPPTP.add_task(&CreateWAVThread::thread_task, pCreateWAVThread);
+        std::lock_guard<std::mutex> lock(m_mutexCreateWAVThreads);
+        m_createWAVThreads.push_back(pCreateWAVThread);
+    }
     
 
     /* 创建计算音量的线程 */
     threadInfo.threadType = EThreadType::Type_CreateDB;
-    // CreateDBThread* pCreateDBThread = new CreateDBThread(threadInfo);
-    // if(pCreateDBThread == nullptr)
-    // {
-    //     SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建计算音量线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
-    //     // return false; // 创建失败
-    // }else 
-    // {
-    //     CPPTP.add_task(&CreateDBThread::thread_task, pCreateDBThread);
-    //     std::lock_guard<std::mutex> lock(m_mutexCreateDBThreads);
-    //     m_createDBThreads.push_back(pCreateDBThread);
-    // }
+    CreateDBThread* pCreateDBThread = new CreateDBThread(threadInfo);
+    if(pCreateDBThread == nullptr)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建计算音量线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
+        // return false; // 创建失败
+    }else 
+    {
+        CPPTP.add_task(&CreateDBThread::thread_task, pCreateDBThread);
+        std::lock_guard<std::mutex> lock(m_mutexCreateDBThreads);
+        m_createDBThreads.push_back(pCreateDBThread);
+    }
 
     /* 创建生成长文件的线程 */
     threadInfo.threadType = EThreadType::Type_CreateLongWAV;
-    // CreateRecordFileThread* pCreateLongWAVThread = new CreateRecordFileThread(threadInfo);
-    // if(pCreateLongWAVThread == nullptr)
-    // {
-    //     SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建生成长文件线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
-    //     // return false; // 创建失败
-    // }else 
-    // {
-    //     CPPTP.add_task(&CreateRecordFileThread::thread_task, pCreateLongWAVThread);
-    //     std::lock_guard<std::mutex> lock(m_mutexCreateLongWAVThreads);
-    //     m_createLongWAVThreads.push_back(pCreateLongWAVThread);
-    // }
+    CreateRecordFileThread* pCreateLongWAVThread = new CreateRecordFileThread(threadInfo);
+    if(pCreateLongWAVThread == nullptr)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建生成长文件线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
+        // return false; // 创建失败
+    }else 
+    {
+        CPPTP.add_task(&CreateRecordFileThread::thread_task, pCreateLongWAVThread);
+        std::lock_guard<std::mutex> lock(m_mutexCreateLongWAVThreads);
+        m_createLongWAVThreads.push_back(pCreateLongWAVThread);
+    }
     
     /* 创建发送RTP数据的线程 */
     threadInfo.threadType = EThreadType::Type_RtpSend;
-    // CPPTP.add_task(&ThreadManager::thread_RTPSend, threadInfo);
+    CPPTP.add_task(&ThreadManager::thread_RTPSend, threadInfo);
 
     /* 创建分派数据线程 */
     threadInfo.threadType = EThreadType::Type_AssignSrcData;
@@ -309,7 +319,7 @@ bool ThreadManager::removeRecordThread(const OneSoundCardPCMInfo_t& pcmInfo, int
 }
 
 /* 销毁录音线程 */
-void ThreadManager::thread_destroyeRecordThread()
+void ThreadManager::destroyeRecordThread()
 {
     std::unique_lock<std::mutex> m_lock(m_mutexRecordThreadRefCount);
     m_condVarDestroyRecord.wait(m_lock, [this]() {
@@ -329,7 +339,7 @@ void ThreadManager::thread_destroyeRecordThread()
             BaseRecordThread* pThread = *it;
             if(pThread != nullptr)
             {
-                auto threadState = pThread->getThreadInfo().threadState;
+                auto threadState = pThread->getThreadInfo().threadState.load();
                 if(EThreadState::State_Stopped == threadState ||
                    EThreadState::State_Error == threadState )
                 {
@@ -355,7 +365,7 @@ void ThreadManager::thread_destroyeRecordThread()
             BaseRecordThread* pThread = *it;
             if(pThread != nullptr)
             {
-                auto threadState = pThread->getThreadInfo().threadState;
+                auto threadState = pThread->getThreadInfo().threadState.load();
                 if(EThreadState::State_Stopped == threadState ||
                    EThreadState::State_Error == threadState )
                 {
@@ -381,7 +391,7 @@ void ThreadManager::thread_destroyeRecordThread()
             BaseRecordThread* pThread = *it;
             if(pThread != nullptr)
             {
-                auto threadState = pThread->getThreadInfo().threadState;
+                auto threadState = pThread->getThreadInfo().threadState.load();
                 if(EThreadState::State_Stopped == threadState ||
                    EThreadState::State_Error == threadState )
                 {
@@ -407,7 +417,7 @@ void ThreadManager::thread_destroyeRecordThread()
             BaseRecordThread* pThread = *it;
             if(pThread != nullptr)
             {
-                auto threadState = pThread->getThreadInfo().threadState;
+                auto threadState = pThread->getThreadInfo().threadState.load();
                 if(EThreadState::State_Stopped == threadState ||
                    EThreadState::State_Error == threadState )
                 {
@@ -433,7 +443,7 @@ void ThreadManager::thread_destroyeRecordThread()
             BaseRecordThread* pThread = *it;
             if(pThread != nullptr)
             {
-                auto threadState = pThread->getThreadInfo().threadState;
+                auto threadState = pThread->getThreadInfo().threadState.load();
                 if(EThreadState::State_Stopped == threadState ||
                    EThreadState::State_Error == threadState )
                 {
@@ -459,7 +469,7 @@ void ThreadManager::thread_destroyeRecordThread()
             BaseRecordThread* pThread = *it;
             if(pThread != nullptr)
             {
-                auto threadState = pThread->getThreadInfo().threadState;
+                auto threadState = pThread->getThreadInfo().threadState.load();
                 if(EThreadState::State_Stopped == threadState ||
                    EThreadState::State_Error == threadState )
                 {

+ 5 - 2
Server/ThreadManager/ThreadManager.h

@@ -46,6 +46,9 @@ public:
     /* 停止所有线程 */
     void stopAllThreads();
 
+    /* 线程函数,销毁录音线程 */
+    void thread_destroyeRecordThread();
+
     /* -------------------------------------------------------------------------------------------
         创建录音线程,传入声卡编号和录音通道编号
         录音线程是统一创建的,有一路录音通道,就会有所有的对应的原始音频处理线程
@@ -59,8 +62,8 @@ public:
     bool removeRecordThread(const OneSoundCardPCMInfo_t& pcmInfo, int compareItemID);
     /* 获取是否需要销毁录音线程实例 */
     bool isDestroyeRecordThread() const { return m_isDestroyeRecordThread.load(); }
-    /* 销毁录音线程,在ACAServer初始化时创建 */
-    void thread_destroyeRecordThread();
+    /* 销毁录音线程函数 */
+    void destroyeRecordThread();
     
 
 

+ 3 - 3
Server/ThreadManager/ThreadWriteDBManager.cpp

@@ -289,7 +289,7 @@ bool ThreadWriteDBManager::processFilePath(QString& strFilePath)
         注意: 这个函数需要在删除数据库记录之前执行,删除文件路径是从数据库中读取的 */
 void ThreadWriteDBManager::deleteTimeoutFile()
 {
-    if(m_lastDeleteFileTime.secsTo(m_currentTime) < 600)
+    if(m_lastDeleteFileTime.secsTo(m_currentTime) < 6)
     {
         return; // 十分钟检查一次
     }
@@ -298,7 +298,7 @@ void ThreadWriteDBManager::deleteTimeoutFile()
     /* 删除录音文件 */
     deleteTimeoutRecordFile();
     
-    /* 删除报警问价 */
+    /* 删除报警文件 */
     deleteTimeoutAlarmFile();
 }
 
@@ -392,7 +392,7 @@ void ThreadWriteDBManager::deleteTimeoutAlarmFile()
             }
         } else 
         {
-            SPDLOG_LOGGER_WARN(m_logger, "报警文件 {} 不存在", fullPath.toStdString());
+            SPDLOG_LOGGER_WARN(m_logger, "删除报警音频文件失败,报警文件 {} 不存在", fullPath.toStdString());
         }
         alarm.fileState = eRecordState::eRS_Deleted;
     }

+ 24 - 37
Server/ThreadRecord/AssignSrcDataThread.cpp

@@ -245,43 +245,30 @@ bool AssignSrcDataThread::getDispatchThread()
     /* 根据生成数据文件的类型顺序获取,循环获取,直到所有的线程都获取到 */
 
     /* 先获取生成wav小文件的线程 */
-    // auto pWavThread = ThreadMan.findRecordThread(EThreadType::Type_CreateWAV, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
-    // if(pWavThread != nullptr)
-    // {
-    //     m_pThreadCreateWAV = dynamic_cast<CreateWAVThread*>(pWavThread);
-    // }
-    // /* 获取生成音量和反相数据的线程 */
-    // auto pDBAndPhaseThread = ThreadMan.findRecordThread(EThreadType::Type_CreateDB, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
-    // if(pDBAndPhaseThread != nullptr)
-    // {
-    //     m_pThreadCreateDB = dynamic_cast<CreateDBThread*>(pDBAndPhaseThread);
-    // }
-    // /* 获取生成长文件的线程 */
-    // auto pLongFileThread = ThreadMan.findRecordThread(EThreadType::Type_CreateLongWAV, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
-    // if(pLongFileThread != nullptr )
-    // {
-    //     m_pThreadCreateLongFile = dynamic_cast<CreateRecordFileThread*>(pLongFileThread);
-    // }
-    // /* 获取发送RTP数据的线程 */
-    // m_rtpSenderThread = ThreadMan.findRecordThread(EThreadType::Type_RtpSend, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
-    // if(m_rtpSenderThread == nullptr)
-    // {
-    //     // SPDLOG_LOGGER_ERROR(m_logger, "{} 获取RTP发送线程失败", m_logBase);
-    //     // return false;
-    // }
-
-    /* 最后获取录音线程信息,如果获取不到则一直获取 */
-    // while(true)
-    // {
-    //     auto pThreadBase = ThreadMan.findRecordThread(EThreadType::Type_RecordSrc, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
-    //     if(pThreadBase != nullptr)
-    //     {
-    //         m_pThreadRecord = dynamic_cast<RecordThread*>(pThreadBase);
-    //         break; // 找到录音线程了
-    //     }
-    //     /* 如果没有找到录音线程,则等待一段时间再继续查找 */
-    //     std::this_thread::sleep_for(std::chrono::milliseconds(5));
-    // }
+    auto pWavThread = ThreadMan.findRecordThread(EThreadType::Type_CreateWAV, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
+    if(pWavThread != nullptr)
+    {
+        m_pThreadCreateWAV = dynamic_cast<CreateWAVThread*>(pWavThread);
+    }
+    /* 获取生成音量数据的线程 */
+    auto pDBAndPhaseThread = ThreadMan.findRecordThread(EThreadType::Type_CreateDB, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
+    if(pDBAndPhaseThread != nullptr)
+    {
+        m_pThreadCreateDB = dynamic_cast<CreateDBThread*>(pDBAndPhaseThread);
+    }
+    /* 获取生成长文件的线程 */
+    auto pLongFileThread = ThreadMan.findRecordThread(EThreadType::Type_CreateLongWAV, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
+    if(pLongFileThread != nullptr )
+    {
+        m_pThreadCreateLongFile = dynamic_cast<CreateRecordFileThread*>(pLongFileThread);
+    }
+    /* 获取发送RTP数据的线程 */
+    m_rtpSenderThread = ThreadMan.findRecordThread(EThreadType::Type_RtpSend, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
+    if(m_rtpSenderThread == nullptr)
+    {
+        // SPDLOG_LOGGER_ERROR(m_logger, "{} 获取RTP发送线程失败", m_logBase);
+        // return false;
+    }
 
     return true;
 }

+ 2 - 1
Server/ThreadRecord/CreateRecordFileThread.cpp

@@ -239,7 +239,7 @@ void CreateRecordFileThread::task()
 /* 初始化一些数据 */
 bool CreateRecordFileThread::initData()
 {
-    m_logBase = fmt::format("录音通道 {}:{} - 记录长文件线程", 
+    m_logBase = fmt::format("录音通道 {}:{} - 录音文件线程", 
         m_threadInfo.cardRoadInfo.strSoundCardName, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
     /* 获取全局数据 */
     m_sampleRate = GInfo.sampleRate();          /* 采样率 */
@@ -268,6 +268,7 @@ void CreateRecordFileThread::clearData()
     /* 清理缓存数据 */
     std::lock_guard<std::mutex> lock(m_mutexBuffer);
     m_bufferData.clear();
+    m_srcData.clear();
 
     std::lock_guard<std::mutex> lockSrcData(m_ringQueue.mutex);
     while(!m_ringQueue.isEmpty())

+ 9 - 5
Server/ThreadRecord/CreateWAVThread.cpp

@@ -18,7 +18,7 @@ CreateWAVThread::CreateWAVThread(RecordThreadInfo_t& threadInfo)
     
 CreateWAVThread::~CreateWAVThread()
 {
-    clearData();
+    // SPDLOG_LOGGER_ERROR(m_logger, "{} ~CreateWAVThread()", m_logBase);
 }
 
 
@@ -244,6 +244,7 @@ void CreateWAVThread::clearData()
     deleteWAVFile(0); // 删除所有文件
     m_listDeleteFile.clear();
 
+    // SPDLOG_LOGGER_ERROR(m_logger, "{} 开始清空 CreateWAV m_queueLeftRightData, 当前数据大小: {}", m_logBase, m_queueLeftRightData.QueueSize());
     std::lock_guard<std::mutex> lock(m_queueLeftRightData.mutex);
     while(!m_queueLeftRightData.isEmpty())
     {
@@ -252,8 +253,11 @@ void CreateWAVThread::clearData()
         {
             delete data;
             data = nullptr;
+        }else {
+            SPDLOG_LOGGER_WARN(m_logger, "{} m_queueLeftRightData 中有空数据", m_logBase);
         }
     }
+    // SPDLOG_LOGGER_ERROR(m_logger, "{} CreateWAV m_queueLeftRightData清空完成, 当前数据大小: {}", m_logBase, m_queueLeftRightData.QueueSize());
 }
 
 /**
@@ -474,13 +478,13 @@ bool CreateWAVThread::splitLeftRightChannel()
     m_queueLeftRightData.mutex.unlock();
     if(tmp != nullptr)
     {
-        // SPDLOG_LOGGER_TRACE(m_logger, "{} 左右声道环形队列已满,出队一个元素", m_logBase);
+        // SPDLOG_LOGGER_WARN(m_logger, "{} 左右声道环形队列已满,出队一个元素", m_logBase);
         delete tmp; // 删除出队的元素
         tmp = nullptr;
     }
-    int leftSize = pLeftRightData->vecLeftData.size() * sizeof(double) * 2;
-    SPDLOG_LOGGER_DEBUG(m_logger, "{} 队列数据数目: {}, 左声道数据大小: {}, 单个元素大小: {}", 
-        m_logBase, m_queueLeftRightData.QueueSize(), pLeftRightData->vecLeftData.size(), leftSize);
+    // int leftSize = pLeftRightData->vecLeftData.size() * sizeof(double) * 2;
+    // SPDLOG_LOGGER_DEBUG(m_logger, "{} 队列数据数目: {}, 左声道数据大小: {}, 单个元素大小: {}", 
+    //     m_logBase, m_queueLeftRightData.QueueSize(), pLeftRightData->vecLeftData.size(), leftSize);
 
     return true;
 }

+ 1 - 1
Server/main.cpp

@@ -31,7 +31,7 @@ int main(int argc, char* argv[])
         return -1;
     }
     SPDLOG_LOGGER_INFO(logger, "★  ★  ★  ★  ★  ★  ★  ☆  ACAServer  ☆  ★  ★  ★  ★  ★  ★  ★");
-    SPDLOG_LOGGER_INFO(logger, "ACServer Version: {}", "6.0.0.1");
+    SPDLOG_LOGGER_INFO(logger, "ACServer Version: {}", "6.0.0.2");
     /* 设置线程池最大线程个数 */
     CPPTP.setThreadMaxNum(1024);
 

+ 2 - 2
SettingLibrary/Modules/AICompare/aicomparewidget.ui

@@ -89,7 +89,7 @@
       <item row="2" column="0">
        <widget class="QLabel" name="label_4">
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;不相似度&lt;/span&gt;阈值:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;不相似度阈值:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -125,7 +125,7 @@
       <item row="3" column="0">
        <widget class="QLabel" name="label_5">
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;相似度&lt;/span&gt;阈值:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;相似度阈值:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>

+ 6 - 6
SettingLibrary/Modules/Database/databasewidget.ui

@@ -97,7 +97,7 @@
       <item row="5" column="0">
        <widget class="QLabel" name="label_5">
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;RTP监听&lt;/span&gt;端口:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;RTP监听端口:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -208,7 +208,7 @@
       <item row="9" column="0">
        <widget class="QLabel" name="label_10">
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;FTP用户密码&lt;/span&gt;:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;FTP用户密码:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -234,7 +234,7 @@
       <item row="8" column="0">
        <widget class="QLabel" name="label_9">
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;FTP用户名&lt;/span&gt;:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;FTP用户名:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -302,7 +302,7 @@
       <item row="6" column="0">
        <widget class="QLabel" name="label_7">
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;录音文件目录:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;录音文件目录:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -312,7 +312,7 @@
       <item row="7" column="0">
        <widget class="QLabel" name="label_8">
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;FTP文件&lt;/span&gt;目录:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;FTP文件目录:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -338,7 +338,7 @@
       <item row="4" column="0">
        <widget class="QLabel" name="label_6">
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;报警文件保留:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;报警文件保留:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>

+ 6 - 6
SettingLibrary/Modules/Noise/noisemonitorparamwidget.ui

@@ -133,7 +133,7 @@
          </size>
         </property>
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;分贝阈值&lt;/span&gt;:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;分贝阈值:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -191,7 +191,7 @@
          </size>
         </property>
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;单次&lt;/span&gt;噪音检测时长(秒):&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;单次噪音检测时长(秒):</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -235,7 +235,7 @@
          </size>
         </property>
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;静音阈值:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;静音阈值:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -267,7 +267,7 @@
          </size>
         </property>
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;重叠样本数&lt;/span&gt;:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;重叠样本数:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -296,7 +296,7 @@
          </size>
         </property>
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;变异系数阈值&lt;/span&gt;:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;变异系数阈值:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -362,7 +362,7 @@
          </size>
         </property>
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;FFT点数&lt;/span&gt;:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;FTP点数:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>

+ 16 - 1
common/GlobalInfo/GlobalVariable.cpp

@@ -285,6 +285,21 @@ bool DetectPeriodConfig_t::isBaseInfoChanged(const DetectPeriodConfig_t &other)
 
 
 
+RecordThreadInfo_t& RecordThreadInfo_t::operator=(const RecordThreadInfo_t& obj)
+{
+    if (this == &obj)
+    {
+        return *this; // 防止自赋值
+    }
+    cardRoadInfo = obj.cardRoadInfo;
+    threadType = obj.threadType;
+    threadState.store(obj.threadState.load());
+
+    return *this;
+}
+
+
+
 /* =========================================================================================
  * 计算线程信息结构体
  * =========================================================================================*/
@@ -300,7 +315,7 @@ CalculateThreadInfo_t& CalculateThreadInfo_t::operator=(const CalculateThreadInf
         return *this; // 防止自赋值
     }
     compareItemInfo = info.compareItemInfo;
-    threadState = info.threadState;
+    threadState.store(info.threadState.load());
     threadType = info.threadType;
     // pThread = info.pThread;
 

+ 6 - 2
common/GlobalInfo/GlobalVariable.h

@@ -402,8 +402,12 @@ struct RecordThreadInfo_t
     // SoundCardRoadInfo_t cardRoadInfo;           /* 录音通道信息 */
     OneSoundCardPCMInfo_t cardRoadInfo;         /* 录音通道信息,包含声卡名称和PCM名称 */
     EThreadType threadType;                     /* 线程类型 */
-    EThreadState threadState;                   /* 线程状态 */
+    std::atomic<EThreadState> threadState;      /* 线程状态 */
     // BaseRecordThread* pThread = nullptr;        /* 线程对象 */
+
+    RecordThreadInfo_t() = default;
+    RecordThreadInfo_t(const RecordThreadInfo_t& obj) { *this = obj; }
+    RecordThreadInfo_t& operator=(const RecordThreadInfo_t& obj);
 };
 
 
@@ -421,7 +425,7 @@ struct CalculateThreadInfo_t
     CompareItemInfo_t compareItemInfo;              /* 对比项信息 */
 
     EThreadType threadType;                         /* 线程类型 */
-    EThreadState threadState;                       /* 线程状态 */
+    std::atomic<EThreadState> threadState;          /* 线程状态 */
     // BaseCalculateThread* pThread = nullptr;         /* 计算线程对象 */
 
     CalculateThreadInfo_t() = default;

+ 2 - 1
common/Network/FromWebAPI.cpp

@@ -909,8 +909,9 @@ bool FromWebAPI::updateAlarmFileState(const std::list<AlarmInfo_t>& listAlarm)
 
             json0.push_back(jsonItem);
         }
-
+        // SPDLOG_LOGGER_DEBUG(m_logger, "更新报警文件状态: {}", json0.dump(4));
         QString strSend = QString::fromStdString(json0.dump());
+        // SPDLOG_LOGGER_DEBUG(m_logger, "strSend Size: {}", strSend.size());
         QString strRet;
         int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)

+ 93 - 0
show3/c1.cpp

@@ -0,0 +1,93 @@
+#include "c1.h"
+#include "AudioRecord.h"
+
+#include <chrono>
+#include <thread>
+
+#include "spdlog/spdlog.h"
+#include "RingQueueManualMutex.hpp"
+
+AudioLeftRightData::AudioLeftRightData(int totalSize)
+{
+    // if (totalSize == 0)
+    // {
+    //     SPDLOG_ERROR("AudioLeftRightData::AudioLeftRightData totalSize is 0");
+    //     return;
+    // }
+    this->totalSize = totalSize;
+    vecLeftData.reserve(totalSize);
+	vecRightData.reserve(totalSize);
+    startTime = QDateTime();
+	endTime = QDateTime();
+	numMSecond = 0;
+}
+
+AudioLeftRightData::~AudioLeftRightData()
+{
+    
+}
+
+AudioLeftRightData::AudioLeftRightData(const AudioLeftRightData& obj)
+{
+    *this = obj; // 使用赋值运算符进行深拷贝
+}
+
+AudioLeftRightData& AudioLeftRightData::operator=(const AudioLeftRightData &obj)
+{
+    if (this == &obj)
+    {
+        return *this; // 防止自赋值
+    }
+    // 释放原有资源
+    vecLeftData.clear();
+    vecRightData.clear();
+    // 复制数据
+    totalSize = obj.totalSize;
+	vecLeftData = obj.vecLeftData;
+	vecRightData = obj.vecRightData;
+	// 复制时间戳
+    startTime = obj.startTime;
+	endTime = obj.endTime;
+	numMSecond = obj.numMSecond;
+
+    return *this;
+}
+
+
+
+
+void c1::test1()
+{
+    RingQueueManualMutex<AudioLeftRightData*> listData(10);
+    SPDLOG_INFO("开始添加 listData 数据");
+    for(int i = 0; i < 10; ++i)
+    {
+        AudioLeftRightData* data = new AudioLeftRightData(48000);
+        for(int j = 0; j < 48000; ++j)
+        {
+            data->vecLeftData.push_back(0.5); // 模拟数据
+            data->vecRightData.push_back(0.5); // 模拟数据
+        }
+        listData.push(data);
+
+        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    }
+    SPDLOG_INFO("添加 listData 数据完成, 当前数据大小: {}", listData.QueueSize());
+    std::this_thread::sleep_for(std::chrono::milliseconds(10000));
+    /* 开始释放数据 */
+    SPDLOG_INFO("开始释放 listData 数据");
+
+    while (!listData.isEmpty())
+    {
+        AudioLeftRightData* data = listData.front_pop();
+        if(data != nullptr)
+        {
+            delete data;
+            data = nullptr;
+        }
+    }
+    SPDLOG_INFO("释放 listData 数据完成");
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(5000));
+    SPDLOG_INFO("结束 test1");
+}

+ 39 - 0
show3/c1.h

@@ -0,0 +1,39 @@
+#ifndef __C1_H__
+#define __C1_H__
+
+
+#include <QDateTime>
+#include <vector>
+
+struct AudioLeftRightData
+{
+    AudioLeftRightData(int totalSize);
+    ~AudioLeftRightData();
+    AudioLeftRightData(const AudioLeftRightData& obj);
+    AudioLeftRightData& operator=(const AudioLeftRightData &obj);
+
+    
+    /* 音频数据 */
+    std::vector<double> vecLeftData;        /* 左声道数据 */
+    std::vector<double> vecRightData;       /* 右声道数据 */
+    int totalSize = 0;                      /* 总长度,两个声道的总长度是一样的 */
+    int numMSecond = 0;                     /* 数据对应的毫秒数 */
+    QDateTime startTime;                    /* 开始时间戳 */
+    QDateTime endTime;                      /* 结束时间戳 */
+};
+
+
+namespace c1
+{
+    void test1();
+
+
+
+
+}
+
+
+
+
+
+#endif // __C1_H__

+ 11 - 1
show3/main.cpp

@@ -14,6 +14,8 @@
 #include <QFile>
 #include "AudioRecord.h"
 
+#include "c1.h"
+
 
 void test1();
 void test2();
@@ -40,7 +42,9 @@ int main(int argc, char* argv[])
     // signalstats_wrapper::finalize();
     // test4(argc, argv);
     // test5();
-    test6(argc, argv);
+    // test6(argc, argv);
+
+    c1::test1();
 
     std::this_thread::sleep_for(std::chrono::seconds(2));
 
@@ -240,3 +244,9 @@ void test6(int argc, char** argv)
     AudioDevice::printPCMAudioDevice(devices);
 }
 
+
+void test6()
+{
+
+}
+