|
@@ -10,7 +10,11 @@
|
|
|
#include <QWriteLocker>
|
|
|
#include <QReadLocker>
|
|
|
#include <cstdint>
|
|
|
-#include <qreadwritelock.h>
|
|
|
+
|
|
|
+#include "CreateDBThread.h"
|
|
|
+#include "CreateWAVThread.h"
|
|
|
+#include "CreateLongFileThread.h"
|
|
|
+
|
|
|
|
|
|
|
|
|
AssignSrcDataThread::AssignSrcDataThread(RecordThreadInfo_t& threadInfo)
|
|
@@ -21,11 +25,11 @@ AssignSrcDataThread::AssignSrcDataThread(RecordThreadInfo_t& threadInfo)
|
|
|
|
|
|
AssignSrcDataThread::~AssignSrcDataThread()
|
|
|
{
|
|
|
- if(m_pRwLock != nullptr)
|
|
|
- {
|
|
|
- delete m_pRwLock;
|
|
|
- m_pRwLock = nullptr;
|
|
|
- }
|
|
|
+ // if(m_pRwLock != nullptr)
|
|
|
+ // {
|
|
|
+ // delete m_pRwLock;
|
|
|
+ // m_pRwLock = nullptr;
|
|
|
+ // }
|
|
|
for(auto& audioData : m_listAudioSrcData)
|
|
|
{
|
|
|
if(audioData != nullptr)
|
|
@@ -42,6 +46,14 @@ AssignSrcDataThread::~AssignSrcDataThread()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/* 停止线程 */
|
|
|
+void AssignSrcDataThread::stopThread()
|
|
|
+{
|
|
|
+ m_isRunning = false;
|
|
|
+ m_condDataUpdate.notify_all(); // 通知所有等待的线程
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
/* 设置数据,这里不用 */
|
|
@@ -69,9 +81,17 @@ bool AssignSrcDataThread::setSrcData(const char* srcData, int32_t dataSize, QDat
|
|
|
audioData->appendData(srcData, dataSize);
|
|
|
audioData->endTime = endTime;
|
|
|
/* 获取读写锁 */
|
|
|
- QWriteLocker locker(m_pRwLock);
|
|
|
- m_listAudioSrcData.push_back(audioData);
|
|
|
- m_listDataSize += dataSize; // 更新缓存中的数据大小
|
|
|
+ {
|
|
|
+ // std::lock_guard<QReadWriteLock> lock(m_pRwLock);
|
|
|
+ std::unique_lock<std::mutex> lock(m_mutexDataUpdate);
|
|
|
+ m_listAudioSrcData.push_back(audioData);
|
|
|
+ m_listDataSize += dataSize; // 更新缓存中的数据大小
|
|
|
+ m_isDataUpdate.store(true);
|
|
|
+ }
|
|
|
+ m_condDataUpdate.notify_one();
|
|
|
+
|
|
|
+ // SPDLOG_LOGGER_WARN(m_logger, "{} 收到音频数据: 大小: {}, 时间: {}", m_logBase, dataSize, endTime.toString().toStdString());
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -93,20 +113,39 @@ void AssignSrcDataThread::task()
|
|
|
return;
|
|
|
}
|
|
|
/* 将自身设置到录音线程中 */
|
|
|
- m_pRecordThread->setAssignSrcDataThread(this);
|
|
|
+ m_pThreadRecord->setAssignSrcDataThread(this);
|
|
|
|
|
|
m_isRunning = true;
|
|
|
while(m_isRunning)
|
|
|
{
|
|
|
/* 休眠一段时间 */
|
|
|
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
|
-
|
|
|
+ // std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
|
+ std::unique_lock<std::mutex> lock(m_mutexDataUpdate);
|
|
|
+ m_condDataUpdate.wait(lock, [this] {
|
|
|
+ return (m_isDataUpdate.load() || !m_isRunning.load());
|
|
|
+ });
|
|
|
+ m_isDataUpdate.store(false);
|
|
|
+ // std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
|
|
|
+
|
|
|
/*------------------------------------------------------------------------
|
|
|
- * 获取一个数据并处理数据,将每一个数据都设置成1s大小,将时间设置为这个数据的开始时间
|
|
|
+ * 分派实时数据
|
|
|
*------------------------------------------------------------------------*/
|
|
|
+ /* 获取最新的数据,给其添加开始时间戳 */
|
|
|
+ auto latestData = m_listAudioSrcData.back();
|
|
|
+ if(latestData == nullptr || latestData->isEmpty())
|
|
|
+ {
|
|
|
+ SPDLOG_LOGGER_ERROR(m_logger, "{} 分派数据线程获取到空数据", m_logBase);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ latestData->startTime = previTime(latestData->endTime, latestData->dataSize);
|
|
|
+
|
|
|
/* 将发送数据到Rtp线程 */
|
|
|
- sendSrcDataToRtp();
|
|
|
-
|
|
|
+ sendSrcDataToRtp(*latestData);
|
|
|
+
|
|
|
+
|
|
|
+ /*------------------------------------------------------------------------
|
|
|
+ * 将每一个数据都设置成1s大小,将时间设置为这个数据的开始时间
|
|
|
+ *------------------------------------------------------------------------*/
|
|
|
/* 判断数据是否满足1s大小 */
|
|
|
if(!isFullOneSecondData())
|
|
|
{
|
|
@@ -119,18 +158,16 @@ void AssignSrcDataThread::task()
|
|
|
m_dispatchSrcData->startTime = previTime(m_dispatchSrcData->endTime, m_dispatchSrcData->dataSize);
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
|
- * 分派数据
|
|
|
+ * 分派常规数据
|
|
|
*------------------------------------------------------------------------*/
|
|
|
/* 分派数据给各个线程 */
|
|
|
- for(auto& dispatchThread : m_listDispatchThreads)
|
|
|
- {
|
|
|
- if(dispatchThread != nullptr)
|
|
|
- {
|
|
|
- dispatchThread->setData(*m_dispatchSrcData);
|
|
|
- }
|
|
|
- }
|
|
|
+ sendRegularData(*m_dispatchSrcData);
|
|
|
/* 清空分派数据 */
|
|
|
m_dispatchSrcData->clear();
|
|
|
+
|
|
|
+ // std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now();
|
|
|
+ // auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime);
|
|
|
+ // SPDLOG_LOGGER_TRACE(m_logger, "{} 分派数据耗时: {}us", m_logBase, duration.count());
|
|
|
}
|
|
|
/* 清理数据 */
|
|
|
clearData();
|
|
@@ -153,8 +190,10 @@ bool AssignSrcDataThread::initData()
|
|
|
|
|
|
m_dispatchSrcData = new AudioSrcData(m_oneSecondSize);
|
|
|
|
|
|
+ m_lastSendTime = QDateTime::currentDateTime(); // 初始化最后发送时间
|
|
|
+
|
|
|
/* 初始化读写锁 */
|
|
|
- m_pRwLock = new QReadWriteLock();
|
|
|
+ // m_pRwLock = new QReadWriteLock();
|
|
|
|
|
|
return true;
|
|
|
}
|
|
@@ -192,19 +231,22 @@ bool AssignSrcDataThread::getDispatchThread()
|
|
|
auto pWavThread = ThreadMan.findRecordThread(EThreadType::Type_CreateWAV, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
|
|
|
if(pWavThread != nullptr)
|
|
|
{
|
|
|
- m_listDispatchThreads.push_back(dynamic_cast<BaseRecordThread*>(pWavThread));
|
|
|
+ // m_listDispatchThreads.push_back(dynamic_cast<BaseRecordThread*>(pWavThread));
|
|
|
+ m_pThreadCreateWAV = dynamic_cast<CreateWAVThread*>(pWavThread);
|
|
|
}
|
|
|
/* 获取生成音量和反相数据的线程 */
|
|
|
auto pDBAndPhaseThread = ThreadMan.findRecordThread(EThreadType::Type_CreateDB, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
|
|
|
if(pDBAndPhaseThread != nullptr)
|
|
|
{
|
|
|
- m_listDispatchThreads.push_back(dynamic_cast<BaseRecordThread*>(pDBAndPhaseThread));
|
|
|
+ // m_listDispatchThreads.push_back(dynamic_cast<BaseRecordThread*>(pDBAndPhaseThread));
|
|
|
+ m_pThreadCreateDB = dynamic_cast<CreateDBThread*>(pDBAndPhaseThread);
|
|
|
}
|
|
|
/* 获取生成长文件的线程 */
|
|
|
auto pLongFileThread = ThreadMan.findRecordThread(EThreadType::Type_CreateLongWAV, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
|
|
|
if(pLongFileThread != nullptr )
|
|
|
{
|
|
|
- m_listDispatchThreads.push_back(dynamic_cast<BaseRecordThread*>(pLongFileThread));
|
|
|
+ // m_listDispatchThreads.push_back(dynamic_cast<BaseRecordThread*>(pLongFileThread));
|
|
|
+ m_pThreadCreateLongFile = dynamic_cast<CreateLongFileThread*>(pLongFileThread);
|
|
|
}
|
|
|
/* 获取发送RTP数据的线程 */
|
|
|
m_rtpSenderThread = ThreadMan.findRecordThread(EThreadType::Type_RtpSend, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
|
|
@@ -220,7 +262,7 @@ bool AssignSrcDataThread::getDispatchThread()
|
|
|
auto pThreadBase = ThreadMan.findRecordThread(EThreadType::Type_RecordSrc, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
|
|
|
if(pThreadBase != nullptr)
|
|
|
{
|
|
|
- m_pRecordThread = dynamic_cast<RecordThread*>(pThreadBase);
|
|
|
+ m_pThreadRecord = dynamic_cast<RecordThread*>(pThreadBase);
|
|
|
break; // 找到录音线程了
|
|
|
}
|
|
|
/* 如果没有找到录音线程,则等待一段时间再继续查找 */
|
|
@@ -233,7 +275,7 @@ bool AssignSrcDataThread::getDispatchThread()
|
|
|
/* 判断是否满足1秒的数据 */
|
|
|
bool AssignSrcDataThread::isFullOneSecondData() const
|
|
|
{
|
|
|
- QReadLocker locker(m_pRwLock);
|
|
|
+ // QReadLocker locker(m_pRwLock);
|
|
|
/* 判断缓存中的数据是否满足1秒大小 */
|
|
|
if(m_listDataSize + m_remainingDataSize >= m_oneSecondSize)
|
|
|
{
|
|
@@ -273,10 +315,8 @@ bool AssignSrcDataThread::processData()
|
|
|
} else
|
|
|
{
|
|
|
/* 取出最新的一个数据,这里只取出数据,不进行数据拷贝,数据处理进入下一个循环后再处理 */
|
|
|
- m_pRwLock->lockForRead();
|
|
|
m_pCurrentSrcData = m_listAudioSrcData.front();
|
|
|
m_listAudioSrcData.pop_front();
|
|
|
- m_pRwLock->unlock();
|
|
|
if(m_pCurrentSrcData == nullptr)
|
|
|
{
|
|
|
break;
|
|
@@ -298,64 +338,73 @@ bool AssignSrcDataThread::processData()
|
|
|
}
|
|
|
|
|
|
/* 发送原始数据到Rtp中,实时发送,有新的就发送 */
|
|
|
-void AssignSrcDataThread::sendSrcDataToRtp()
|
|
|
+void AssignSrcDataThread::sendSrcDataToRtp(const AudioSrcData& srcData)
|
|
|
{
|
|
|
- QReadLocker locker(m_pRwLock);
|
|
|
+ // QReadLocker locker(m_pRwLock);
|
|
|
if(m_rtpSenderThread == nullptr)
|
|
|
{
|
|
|
return; // 如果没有RTP发送线程,则直接返回
|
|
|
}
|
|
|
+
|
|
|
+ m_rtpSenderThread->setData(srcData);
|
|
|
|
|
|
- if(m_listAudioSrcData.empty())
|
|
|
+ // if(m_listAudioSrcData.empty())
|
|
|
+ // {
|
|
|
+ // return; // 如果没有数据,则直接返回
|
|
|
+ // }
|
|
|
+
|
|
|
+ // SPDLOG_LOGGER_DEBUG(m_logger, "{} 发送RTP数据,队列大小: {}, 开始时间: {}, 当前时间:{}",
|
|
|
+ // m_logBase, m_listAudioSrcData.count(), m_listAudioSrcData.back()->startTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(),
|
|
|
+ // m_lastSendTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString());
|
|
|
+
|
|
|
+ // auto it = m_listAudioSrcData.end();
|
|
|
+ // if(it != m_listAudioSrcData.begin())
|
|
|
+ // {
|
|
|
+ // --it; // 移动到最后一个数据
|
|
|
+ // }
|
|
|
+
|
|
|
+ // /* 已发送过数据,获取这个数据在队列中的位置,然后发送剩余的数据 */
|
|
|
+ // for(; it != m_listAudioSrcData.begin(); --it)
|
|
|
+ // {
|
|
|
+ // if((*it)->startTime == m_lastSendTime)
|
|
|
+ // {
|
|
|
+ // break; // 找到已发送数据的位置
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // if(it == m_listAudioSrcData.begin())
|
|
|
+ // {
|
|
|
+ // SPDLOG_LOGGER_TRACE(m_logger, "{} RTP线程需要拷贝全部数据", m_logBase);
|
|
|
+ // }
|
|
|
+ // /* 开始发送数据 */
|
|
|
+ // for(; it != m_listAudioSrcData.end(); ++it)
|
|
|
+ // {
|
|
|
+ // if(*it != nullptr)
|
|
|
+ // {
|
|
|
+ // m_rtpSenderThread->setData(**it);
|
|
|
+ // m_lastSendTime = (*it)->startTime; // 更新已发送数据
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* 发送常规数据,对实时性要求不高的数据,数据时长1秒 */
|
|
|
+void AssignSrcDataThread::sendRegularData(const AudioSrcData& srcData)
|
|
|
+{
|
|
|
+ /* 发送计算音量的数据 */
|
|
|
+ if(m_pThreadCreateWAV != nullptr)
|
|
|
{
|
|
|
- return; // 如果没有数据,则直接返回
|
|
|
+ m_pThreadCreateWAV->setData(srcData);
|
|
|
}
|
|
|
- /* 如果发送数据和最新的数据不一样,则发送数据 */
|
|
|
- if(m_pSendSrcData == nullptr)
|
|
|
+ /* 发送生成wav小文件的数据 */
|
|
|
+ if(m_pThreadCreateDB != nullptr)
|
|
|
{
|
|
|
- /* 还未发送过,直接发送所有数据 */
|
|
|
- for(auto& audioData : m_listAudioSrcData)
|
|
|
- {
|
|
|
- if(audioData != nullptr)
|
|
|
- {
|
|
|
- m_rtpSenderThread->setData(*audioData);
|
|
|
- m_pSendSrcData = audioData; // 更新已发送数据
|
|
|
- }
|
|
|
- }
|
|
|
- }else
|
|
|
+ m_pThreadCreateDB->setData(srcData);
|
|
|
+ }
|
|
|
+ /* 发送生成长文件的数据 */
|
|
|
+ if(m_pThreadCreateLongFile != nullptr)
|
|
|
{
|
|
|
- /* 已发送过数据,获取这个数据在队列中的位置,然后发送剩余的数据 */
|
|
|
- auto it = m_listAudioSrcData.begin();
|
|
|
- for(; it != m_listAudioSrcData.end(); ++it)
|
|
|
- {
|
|
|
- if(*it == m_pSendSrcData)
|
|
|
- {
|
|
|
- break; // 找到已发送数据的位置
|
|
|
- }
|
|
|
- }
|
|
|
- if(it != m_listAudioSrcData.end())
|
|
|
- {
|
|
|
- ++it; // 移动到下一个数据
|
|
|
- for(; it != m_listAudioSrcData.end(); ++it)
|
|
|
- {
|
|
|
- if(*it != nullptr)
|
|
|
- {
|
|
|
- m_rtpSenderThread->setData(**it);
|
|
|
- m_pSendSrcData = *it; // 更新已发送数据
|
|
|
- }
|
|
|
- }
|
|
|
- }else
|
|
|
- {
|
|
|
- /* 没有找到相等的,说明这个队列中是全新的数据,所有的都需要发送 */
|
|
|
- for(auto& audioData : m_listAudioSrcData)
|
|
|
- {
|
|
|
- if(audioData != nullptr)
|
|
|
- {
|
|
|
- m_rtpSenderThread->setData(*audioData);
|
|
|
- m_pSendSrcData = audioData; // 更新已发送数据
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ m_pThreadCreateLongFile->setData(srcData);
|
|
|
}
|
|
|
}
|
|
|
|