Files
2026-02-01 22:23:06 +08:00

1121 lines
52 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "datainject.h"
#include <QFileDialog>
#include "mainwindow.h"
#include "../Common/GdImageLib.h"
#include "../Common/GLWidget.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QThread>
#include <QElapsedTimer>
#include <QPainter>
//#define SaveLog
DataInject::DataInject(QObject* parent): QObject(parent)
{
// m_pParentWgt = (MainWindow*)parent;
m_bIsSaveLog = false;
m_pParent = (MainWindow*)parent;
m_bDealRawThreadRunning = false;
m_bInjectThreadRunning = false;
m_bImgProcessThreadRunning = false;
m_ptrThread_InjectData = nullptr;
m_ptrThread_WriteCmd = nullptr;
m_bWriteCmdThreadRunning = false;
// uiThreadSleepTime = 1000;
m_iInjectEnableStatus = 0;
QString logDirName = "Inject_AllChannel";
m_pLog = new QLog(logDirName);
m_pLog->start();
m_pReadFileLog = new QLog("InjectReadFile");
m_pReadFileLog->start();
m_szY8ImgData_Thread01 = new byte[MaxImgHeight * MaxImgWidth + 4096];
m_szY8ImgData_Thread02 = new byte[MaxImgHeight * MaxImgWidth + 4096];
m_szRGBAImgData_Thread01 = new byte[MaxImgHeight * MaxImgWidth * 4 + 4096];
m_szRGBAImgData_Thread02 = new byte[MaxImgHeight * MaxImgWidth * 4 + 4096];
connect(&m_varTimer, &QTimer::timeout, this, [ = ]()
{
for (int i = 0; i < InjectChannelNum; i++)
{
if (m_pLabelMap.value(i))
{
QString str01 = QString("%1/%2")
.arg(m_iFileStreamCurrIndexMap.value(i))
.arg(m_iFileStreamTotalCountMap.value(i));
m_pLabelMap.value(i)->setText(str01);
}
}
});
m_varTimer.setTimerType(Qt::PreciseTimer);
m_varTimer.start(40);
for (int i = 0; i < 9; i++)
{
QVector<QRgb> tmpVector;
for (int j = 0; j < 256; ++j)
{
int b = IRImage_ColorTable[i][j][0];
int g = IRImage_ColorTable[i][j][1];
int r = IRImage_ColorTable[i][j][2];
tmpVector.push_back(qRgb(r, g, b));
}
m_varColorTable.push_back(tmpVector);
}
for (int i = 0; i < InjectChannelNum; i++)
{
m_pOpenGlMap.insert(i, nullptr);
m_pLabelMap.insert(i, nullptr);
m_pGCycleQueueMap.insert(i, nullptr);
m_bIsStartInjectMap.insert(i, false);
m_uiHostWriteBuffNoMap.insert(i, -1);
m_pFullScreenOpenGlMap.insert(i, nullptr);
m_iFileStreamCurrIndexMap.insert(i, 0);
m_iFileStreamTotalCountMap.insert(i, 0);
m_bIsInjectParamSimulateMap.insert(i, false);
m_iDDRBufferCacheSizeMap.insert(i, 0);
m_iVideoFileFrameSizeMap.insert(i, 0);
m_iInjectFrameTotalSizeMap.insert(i, 0);
m_pInjectDataQueueMap.insert(i, 0);
m_varImgDisplayDataQueueMap.insert(i, nullptr);
m_pFileStreamMap.insert(i, nullptr);
m_uiCalcuFramesMap.insert(i, 100);
m_dInjectFrameRateMap.insert(i, 0);
m_iFrameTimeStartMap.insert(i, 0);
m_uiCurrFrameRateCountMap.insert(i, 0);
m_varInjectCMDMap.insert(i, nullptr);
m_pDataInjectLogMap.insert(i, nullptr);
m_pCmdInjectLogMap.insert(i, nullptr);
m_uiInjectFrameNoGenerateMap.insert(i, 0);
}
m_bIsOpenInjectThread = false;
m_bIsHiddenOsd = false;
m_uiAXIFrequence = Pcie_ReadReg(ControlRegBaseAddr + 0x030); //AXI总线频率
}
DataInject::~DataInject()
{
StopThread_DealRawFileData();
StopThread_InjectData();
StopThread_ImgProcessData();
if (m_bWriteCmdThreadRunning)
{
m_pParent->ResetUsedCpuCoreIndex(m_uiCpuCoreIndexUsedMap.value(m_ptrThread_WriteCmd->native_handle()));
m_uiCpuCoreIndexUsedMap.remove(m_ptrThread_WriteCmd->native_handle());
m_bWriteCmdThreadRunning = false;
m_ptrThread_WriteCmd->join();
delete m_ptrThread_WriteCmd;
m_ptrThread_WriteCmd = nullptr;
}
for (int i = 0; i < InjectChannelNum; i++)
{
if (m_varInjectCMDMap.value(i))
{
delete m_varInjectCMDMap.value(i);
}
if (m_pCmdInjectLogMap.value(i))
{
delete m_pCmdInjectLogMap.value(i);
}
}
m_pLog->stop();
}
bool DataInject::StartInject(GFrameFormat* injectParam, void* openglview, void* uiFileProgressLabel)
{
bool bIsStartInject = false;
if (Init(injectParam, openglview, uiFileProgressLabel))
{
//给ThreadFun_FetchRawFileData读文件的时间防止开始几帧无数据 勿删
std::this_thread::sleep_for(std::chrono::milliseconds(50));
m_uiHostWriteBuffNoMap.insert(injectParam->nChannelIndex, -1);
m_bIsStartInjectMap.insert(injectParam->nChannelIndex, true);
bIsStartInject = true;
}
if ((!m_bIsOpenInjectThread) && bIsStartInject)
{
StartThread_DealRawFileData();
std::this_thread::sleep_for(std::chrono::milliseconds(50)); //线程还没起来 勿删
StartThread_InjectData();
StartThread_ImgProcessData();
m_bIsOpenInjectThread = true;
}
if (bIsStartInject)
{
std::this_thread::sleep_for(std::chrono::milliseconds(50)); //线程还没起来 勿删
//09.注入使能状态--控制寄存器 (开始注入时使能,停止注入时关闭使能)
m_iInjectEnableStatus = m_iInjectEnableStatus | ((int)pow(2, (injectParam->nChannelIndex)));
Pcie_WriteReg(ControlRegBaseAddr + 0x01C, (uchar*)&m_iInjectEnableStatus);
}
return bIsStartInject;
}
bool DataInject::Init(GFrameFormat* injectParam, void* openglview, void* uiFileProgressLabel)
{
QString uiFilePath;
if (!BrowseRawFile(uiFilePath))
{
return false;
}
//**************先声明对象, 让线程先跑起来****************
bool m_bRecyclePlay = true;
FileStream* pRawFileStream = new FileStream(false, m_bRecyclePlay, uiFilePath, *injectParam, &DataInject::OnProgress, this);
pRawFileStream->Play();
if (m_pFileStreamMap.value(injectParam->nChannelIndex))
{
delete m_pFileStreamMap.value(injectParam->nChannelIndex);
}
m_pFileStreamMap.insert(injectParam->nChannelIndex, pRawFileStream);
//******************************
int nFileNamePos = uiFilePath.lastIndexOf("/", -1);
if (-1 == nFileNamePos)
{
return false;
}
if (uiFileProgressLabel)
{
m_pLabelMap.insert(injectParam->nChannelIndex, (QLabel*)uiFileProgressLabel);
}
if (openglview)
{
GLWidget* glWgt = (GLWidget*)openglview;
glWgt->Init(injectParam->nImageWidth, injectParam->nImageHeight + injectParam->nParamLineCount);
m_pOpenGlMap.insert(injectParam->nChannelIndex, glWgt);
}
QString logDirName = "Inject0" + QString::number(injectParam->nChannelIndex + 1);
QLog* pQLog = new QLog(logDirName);
pQLog->start();
if (m_pDataInjectLogMap.value(injectParam->nChannelIndex))
{
delete m_pDataInjectLogMap.value(injectParam->nChannelIndex);
}
m_pDataInjectLogMap.insert(injectParam->nChannelIndex, pQLog);
m_frameFormatMap.insert(injectParam->nChannelIndex, *injectParam);
//注入初始化设置 包括缓存buffer地址 数量 大小 图像类型 图像大小 中断触发模式 行周期 帧周期
uint nImgType = 0;
uint iPixalByte = 0;
switch (injectParam->ePT)
{
case ePT_YUV422:
nImgType = 0;
iPixalByte = 2;
break;
case ePT_Y8:
nImgType = 1;
iPixalByte = 1;
break;
case ePT_Y16:
nImgType = 2;
iPixalByte = 2;
break;
case ePT_Y16Y8:
nImgType = 3;
iPixalByte = 3;
break;
case ePT_BGR24:
nImgType = 4;
iPixalByte = 3;
break;
default:
break;
}
//计算每帧数据总字节大小(录像文件)
uint iFileFrameSize = iPixalByte * injectParam->nImageWidth * (injectParam->nImageHeight + injectParam->nParamLineCount);
m_iVideoFileFrameSizeMap.insert(injectParam->nChannelIndex, iFileFrameSize);
GCycleQueue* pImgShowQueue = new GCycleQueue();
pImgShowQueue->InitQueue(iFileFrameSize, DEFAULT_QUEUE_SIZE);
if (m_varImgDisplayDataQueueMap.value(injectParam->nChannelIndex))
{
delete m_varImgDisplayDataQueueMap.value(injectParam->nChannelIndex);
}
m_varImgDisplayDataQueueMap.insert(injectParam->nChannelIndex, pImgShowQueue);
uint iInjectFrameTotalSize = 0;
if (m_bIsInjectParamSimulateMap.value(injectParam->nChannelIndex)) //1行模拟参数行注入
{
iInjectFrameTotalSize = iFileFrameSize + iPixalByte * injectParam->nImageWidth * 1;
}
else //实际文件注入
{
iInjectFrameTotalSize = iFileFrameSize;
}
m_iInjectFrameTotalSizeMap.insert(injectParam->nChannelIndex, iInjectFrameTotalSize);
//****************
GCycleQueue* pInjectQueue = new GCycleQueue();
pInjectQueue->InitQueue(iInjectFrameTotalSize, DEFAULT_QUEUE_SIZE);
if (m_pInjectDataQueueMap.value(injectParam->nChannelIndex))
{
delete m_pInjectDataQueueMap.value(injectParam->nChannelIndex);
}
m_pInjectDataQueueMap.insert(injectParam->nChannelIndex, pInjectQueue);
//******************
uint iCacheMemorySize = (iInjectFrameTotalSize + 2047) / 2048 * 2048; //采集卡DDR buffer缓存大小,按照2048字节向上对齐
m_iDDRBufferCacheSizeMap.insert(injectParam->nChannelIndex, iCacheMemorySize);
uint uiCacheImgSize = 0;
uint uiTotalImageHeight = 0; //计算图像高度方向的像素高
if (m_bIsInjectParamSimulateMap.value(injectParam->nChannelIndex)) //是否含有模拟参数
{
uiTotalImageHeight = injectParam->nImageHeight + injectParam->nParamLineCount + 1; // 1代表上位机界面模拟的一行参数
}
else
{
uiTotalImageHeight = injectParam->nImageHeight + injectParam->nParamLineCount;
}
uiCacheImgSize = uiCacheImgSize >> 16 | injectParam->nImageWidth;
uiCacheImgSize = uiCacheImgSize << 16 | uiTotalImageHeight; //injectParam->nImageHeight
//01.图像类型
Pcie_WriteReg(InjectChannelRegBaseAddr + ((injectParam->nChannelIndex) * 0x1000) + 0x000, (uchar*)&nImgType);
//02.图像大小
Pcie_WriteReg(InjectChannelRegBaseAddr + ((injectParam->nChannelIndex) * 0x1000) + 0x004, (uchar*)&uiCacheImgSize);
//03.缓存数量
uint CacheNum = ChannelCacheNum;
Pcie_WriteReg(InjectChannelRegBaseAddr + ((injectParam->nChannelIndex) * 0x1000) + 0x008, (uchar*)&CacheNum);
//04.每个缓存区域大小
Pcie_WriteReg(InjectChannelRegBaseAddr + ((injectParam->nChannelIndex) * 0x1000) + 0x00C, (uchar*) &iCacheMemorySize);
//05.设置每个通道的4个缓存区的起始地址
for (int n = 0; n < ChannelCacheNum; n++) //todo 此处n的范围是0~7 还是1~8 需要确定
{
uint captureFinalAddr = 0x40000000; //1GB(采集占用DDR前面1GB注入占用DDR后面1GB)
uint injectCacheAddr = captureFinalAddr + (injectParam->nChannelIndex) * ChannelCacheNum * PcieDDR_EachBuffSize + n * PcieDDR_EachBuffSize; //注入 卡DDR中缓存区绝对地址(首地址)
Pcie_WriteReg(InjectChannelRegBaseAddr + ((injectParam->nChannelIndex) * 0x1000) + (0x100 + n * 0x10), (uchar*)&injectCacheAddr);
//将每个Buff的状态设置为空闲
uint iOUTPUT_BUFFERn_STATUS = 0;
Pcie_WriteReg(InjectChannelRegBaseAddr + ((injectParam->nChannelIndex) * 0x1000) + (0x100 + n * 0x10 + 0x8), (uchar*)&iOUTPUT_BUFFERn_STATUS);
}
//07.注入模式
uint nInjectMode = 0;
switch (injectParam->iInMode)
{
case 0: //正常模式
nInjectMode = 0;
break;
case 1: //单帧模式
nInjectMode = 1;
break;
case 2: //测试模式
{
switch (injectParam->eTestImageType)
{
case 0: //递增数
nInjectMode = nInjectMode | 0x00000002;
break;
case 1: //棋盘格
nInjectMode = nInjectMode | 0x00000102;
break;
case 2: //滚动条
nInjectMode = nInjectMode | 0x00000202;
break;
default:
break;
}
}
break;
default:
break;
}
//07.注入模式
Pcie_WriteReg(InjectChannelRegBaseAddr + ((injectParam->nChannelIndex) * 0x1000) + 0x01C, (uchar*)&nInjectMode); //注入模式寄存器设置
uint lineCycle = injectParam->nImgLinePeriod; //图像行周期
uint uiFpgaFreq = Pcie_ReadReg(ControlRegBaseAddr + 0x028); //获取FPGA时钟频率
ULONG FrameCycle = uiFpgaFreq / injectParam->nFrameRate; // 图像帧周期 uiFpgaFreq为FPGA时钟频率依据调试实际情况来
// uiThreadSleepTime = 1000 / injectParam->nFrameRate;
//08.测试图像行周期 帧周期
Pcie_WriteReg(InjectChannelRegBaseAddr + ((injectParam->nChannelIndex) * 0x1000) + 0x020, (uchar*)&lineCycle); //测试图像行周期
Pcie_WriteReg(InjectChannelRegBaseAddr + ((injectParam->nChannelIndex) * 0x1000) + 0x024, (uchar*)&FrameCycle); //测试图像帧周期
// //09.注入使能状态--控制寄存器 (开始注入时使能,停止注入时关闭使能)
// m_iInjectEnableStatus = m_iInjectEnableStatus | ((int)pow(2, (injectParam->nChannelIndex)));
// Pcie_WriteReg(ControlRegBaseAddr + 0x01C, (uchar*)&m_iInjectEnableStatus);
return true;
}
void DataInject::StopInject(int channelIndex)
{
if (!IsStartInject(channelIndex))
{
return;
}
if (m_bIsStartInjectMap.value(channelIndex))
{
//09.注入使能状态--控制寄存器 (停止注入时关闭使能--将指定位的bit置为0其他bit保持不变)
m_iInjectEnableStatus &= ~(1 << (m_frameFormatMap.value(channelIndex).nChannelIndex));
Pcie_WriteReg(ControlRegBaseAddr + 0x01C, (uchar*)&m_iInjectEnableStatus);
m_bIsInjectParamSimulateMap.insert(channelIndex, false);
m_bIsStartInjectMap.insert(channelIndex, false);
m_uiHostWriteBuffNoMap.insert(channelIndex, -1);
m_iFileStreamCurrIndexMap.insert(channelIndex, 0);
m_iFileStreamTotalCountMap.insert(channelIndex, 0);
m_bIsInjectParamSimulateMap.insert(channelIndex, false);
m_iDDRBufferCacheSizeMap.insert(channelIndex, 0);
m_iVideoFileFrameSizeMap.insert(channelIndex, 0);
m_iInjectFrameTotalSizeMap.insert(channelIndex, 0);
m_pInjectDataQueueMap.insert(channelIndex, nullptr);
m_uiCalcuFramesMap.insert(channelIndex, 100);
m_dInjectFrameRateMap.insert(channelIndex, 0);
m_iFrameTimeStartMap.insert(channelIndex, 0);
m_uiCurrFrameRateCountMap.insert(channelIndex, 0);
m_uiInjectFrameNoGenerateMap.insert(channelIndex, 0);
if (m_pDataInjectLogMap.value(channelIndex))
{
m_pDataInjectLogMap.value(channelIndex)->stop();
}
}
SleepAccurate(50);
m_pOpenGlMap.value(channelIndex)->SetStatusBackImg(Normal);
//是否停止线程
bool bIsAnyChannelInject = false;
for (int i = 0; i < m_bIsStartInjectMap.size(); i++)
{
if (m_bIsStartInjectMap.value(i))
{
bIsAnyChannelInject = true;
}
}
qDebug() << "start m_pFileStreamMap.stop" ;
m_pFileStreamMap.value(channelIndex)->Stop();
qDebug() << "finish m_pFileStreamMap.stop" ;
if (!bIsAnyChannelInject)
{
StopThread_DealRawFileData();
StopThread_InjectData();
StopThread_ImgProcessData();
m_bIsOpenInjectThread = false;
}
}
void DataInject::WriteControlCmd(int iChannelIndex, QByteArray cmdData)
{
if (!m_varInjectCMDMap.value(iChannelIndex))
{
m_varInjectCMDMap.insert(iChannelIndex, new DynamicArray());
}
m_varInjectCMDMap.value(iChannelIndex)->PushData(cmdData.data(), cmdData.size());
if (!m_bWriteCmdThreadRunning)
{
uint coreIndex = m_pParent->GetIdealCpuCoreIndex();
m_bWriteCmdThreadRunning = true;
m_ptrThread_WriteCmd = new std::thread(std::bind(&DataInject::ThreadEntry, &DataInject::ThreadFun_WriteCmdControlData, (void*)this));
SetThreadAffinityMask(m_ptrThread_WriteCmd->native_handle(), pow(2, coreIndex)); //与注入共用核
m_uiCpuCoreIndexUsedMap.insert(m_ptrThread_WriteCmd->native_handle(), coreIndex);
}
if (!m_pCmdInjectLogMap.value(iChannelIndex))
{
QString logDirName = "CmdInject0" + QString::number(iChannelIndex + 1);
QLog* pQLog = new QLog(logDirName);
pQLog->start();
m_pCmdInjectLogMap.insert(iChannelIndex, pQLog);
}
}
InjectDelayStatusInfo* DataInject::GetDelayStatus(int channelIndex)
{
for (int n = 0; n < ChannelCacheNum; n++)
{
uint buffAddr = InjectChannelRegBaseAddr + (m_frameFormatMap.value(channelIndex).nChannelIndex * 0x1000) + (0x100 + n * 0x10 + 0x0C);
//上位机注入延时 单位:秒 CPU 开始写入 →CPU 写入 1 帧数据
uint iInjectReg = 0x03;
iInjectReg = iInjectReg << 28;
Pcie_WriteReg(buffAddr, (uchar*)&iInjectReg);
uint bufferCostTime_HostInject = Pcie_ReadReg(buffAddr);
m_szInjectStatus[n].uiHostInjectDelay = double(bufferCostTime_HostInject & 0x0FFFFFFF) / m_uiAXIFrequence; //高四bit置0 转换为秒
//FPGA响应中断的延时 单位:秒
iInjectReg = 0x01;
iInjectReg = iInjectReg << 28;
Pcie_WriteReg(buffAddr, (uchar*)&iInjectReg);
uint bufferCostTime_HostResponseInter = Pcie_ReadReg(buffAddr);
m_szInjectStatus[n].uiFPGADealInterruptDelay = double(bufferCostTime_HostResponseInter & 0x0FFFFFFF) / m_uiAXIFrequence; //高四bit置0 转换为秒
//FPGA输出1帧图像的时间 单位:秒
iInjectReg = 0x02;
iInjectReg = iInjectReg << 28;
Pcie_WriteReg(buffAddr, (uchar*)&iInjectReg);
uint bufferCostTime_FPGACostTime = Pcie_ReadReg(buffAddr);
m_szInjectStatus[n].uiFPGACostTime = double(bufferCostTime_FPGACostTime & 0x0FFFFFFF) / m_uiAXIFrequence; //高四bit置0 转换为秒
//从CPU开始发送到发送中断的时间 单位:秒
iInjectReg = 0x00;
iInjectReg = iInjectReg << 28;
Pcie_WriteReg(buffAddr, (uchar*)&iInjectReg);
uint bufferCostTime_CPUCostTime = Pcie_ReadReg(buffAddr);
m_szInjectStatus[n].uiCPUSendInterCostTime = double(bufferCostTime_CPUCostTime & 0x0FFFFFFF) / m_uiAXIFrequence; //高四bit置0 转换为秒
}
return m_szInjectStatus;
}
void DataInject::SetFullScreenWgt(int channelIndex, void* fullScreenOpenglview)
{
// int imgWidth = m_frameFormatMap.value(channelIndex).nImageWidth;
// int imgHeight = m_frameFormatMap.value(channelIndex).nImageHeight;
// ((GLWidget*)fullScreenOpenglview)->Init(imgWidth, imgHeight);
m_pFullScreenOpenGlMap.insert(channelIndex, (GLWidget*)fullScreenOpenglview);
}
void DataInject::UpdateParamSimulate(int channelindex, bool isInjectParamSimulate, THERMAL_IMG_PARAMS param)
{
m_bIsInjectParamSimulateMap.insert(channelindex, isInjectParamSimulate);
m_varThermalImgParamsMap.insert(channelindex, param);
}
void DataInject::OnProgress(int nFrameIndex, int nFrameCount, void* pOwner, int iChannelIndex)
{
DataInject* pDataInject = reinterpret_cast<DataInject*>(pOwner);
if (nullptr != pDataInject)
{
pDataInject->SetProgress(nFrameIndex, nFrameCount, iChannelIndex);
}
}
void DataInject::SetProgress(int nFrameIndex, int nFrameCount, int iChannelIndex)
{
m_iFileStreamCurrIndexMap.insert(iChannelIndex, nFrameIndex);
m_iFileStreamTotalCountMap.insert(iChannelIndex, nFrameCount);
}
void DataInject::CalcuImgFps(int channelIndex)
{
//帧率计算
int64_t currentTime = std::chrono::system_clock::now().time_since_epoch().count();
if (m_uiCurrFrameRateCountMap.value(channelIndex) == 0)
{
m_iFrameTimeStartMap.insert(channelIndex, currentTime);
}
uint uiCurrFrameRateCount = m_uiCurrFrameRateCountMap.value(channelIndex);
uiCurrFrameRateCount++;
if (uiCurrFrameRateCount > m_uiCalcuFramesMap.value(channelIndex))
{
int64_t tmNow = std::chrono::system_clock::now().time_since_epoch().count();
int64_t nTmSpan = tmNow - m_iFrameTimeStartMap.value(channelIndex);
double dInjectFrameRate = (float)m_uiCalcuFramesMap.value(channelIndex) / (double(nTmSpan) / (1000.0 * 1000.0 * 10));
m_dInjectFrameRateMap.insert(channelIndex, dInjectFrameRate);
uiCurrFrameRateCount = 0;
}
m_uiCurrFrameRateCountMap.insert(channelIndex, uiCurrFrameRateCount);
}
bool DataInject::BrowseRawFile(QString& filePathEdit)
{
QFileDialog varFileDialog((QWidget*)m_pParent);
varFileDialog.setWindowTitle(/*QString("%1").fromLocal8Bit(*/ tr("读取raw文件"));
varFileDialog.setDirectory(tr(""));
Qt::WindowFlags flags = Qt::Dialog | Qt::WindowCloseButtonHint;
varFileDialog.setWindowFlags(flags);
varFileDialog.setModal(true);
// varFileDialog.setOption(QFileDialog::DontUseNativeDialog);
QString strExt = tr("raw files (*.raw *.dat);;all files (*.*) )");
varFileDialog.setNameFilter(strExt);
varFileDialog.move((QApplication::desktop()->width() - varFileDialog.width()) / 2, (QApplication::desktop()->height() - varFileDialog.height()) / 2);
if (QFileDialog::Accepted == varFileDialog.exec())
{
QString strDir = varFileDialog.selectedFiles()[0];
filePathEdit = strDir;
return true;
}
filePathEdit = QString("");
return false;
}
int DataInject::GetByteOfPixel(ePixelType ePT)
{
switch (ePT)
{
case ePT_Y16:
case ePT_Y16U:
case ePT_YV12:
case ePT_YUV422:
case ePT_YUV420P:
{
return 2;
}
case ePT_Y8:
{
return 1;
}
case ePT_Y16Y8:
case ePT_BGR24:
{
return 3;
}
case ePT_RGBA32:
{
return 4;
}
default:
{
break;
}
}
return 1;
}
void DataInject::StopThread_DealRawFileData()
{
if (m_bDealRawThreadRunning)
{
m_pParent->ResetUsedCpuCoreIndex(m_uiCpuCoreIndexUsedMap.value(m_ptrThread_DealRaw01->native_handle()));
m_uiCpuCoreIndexUsedMap.remove(m_ptrThread_DealRaw01->native_handle());
//
m_pParent->ResetUsedCpuCoreIndex(m_uiCpuCoreIndexUsedMap.value(m_ptrThread_DealRaw02->native_handle()));
m_uiCpuCoreIndexUsedMap.remove(m_ptrThread_DealRaw02->native_handle());
m_bDealRawThreadRunning = false;
m_ptrThread_DealRaw01->join();
m_ptrThread_DealRaw02->join();
delete m_ptrThread_DealRaw01;
delete m_ptrThread_DealRaw02;
m_ptrThread_DealRaw01 = nullptr;
m_ptrThread_DealRaw02 = nullptr;
}
}
bool DataInject::StartThread_DealRawFileData()
{
StopThread_DealRawFileData();
m_bDealRawThreadRunning = true;
uint coreIndex = m_pParent->GetIdealCpuCoreIndex();
m_ptrThread_DealRaw01 = new std::thread(std::bind(&DataInject::InjectThreadEntry, &DataInject::ThreadFun_FetchRawFileData, (void*)this, 0));
SetThreadAffinityMask(m_ptrThread_DealRaw01->native_handle(), pow(2, coreIndex));
m_uiCpuCoreIndexUsedMap.insert(m_ptrThread_DealRaw01->native_handle(), coreIndex);
//
coreIndex = m_pParent->GetIdealCpuCoreIndex();
m_ptrThread_DealRaw02 = new std::thread(std::bind(&DataInject::InjectThreadEntry, &DataInject::ThreadFun_FetchRawFileData, (void*)this, 1));
SetThreadAffinityMask(m_ptrThread_DealRaw02->native_handle(), pow(2, coreIndex));
m_uiCpuCoreIndexUsedMap.insert(m_ptrThread_DealRaw02->native_handle(), coreIndex);
return true;
}
bool DataInject::StartThread_InjectData()
{
StopThread_InjectData();
m_bInjectThreadRunning = true;
uint coreIndex = m_pParent->GetIdealCpuCoreIndex();
m_ptrThread_InjectData = new std::thread(std::bind(&DataInject::ThreadEntry, &DataInject::ThreadFun_InjectData, (void*)this));
SetThreadAffinityMask(m_ptrThread_InjectData->native_handle(), pow(2, coreIndex));
m_uiCpuCoreIndexUsedMap.insert(m_ptrThread_InjectData->native_handle(), coreIndex);
return true;
}
bool DataInject::StartThread_ImgProcessData()
{
StopThread_ImgProcessData();
m_bImgProcessThreadRunning = true;
uint coreIndex = m_pParent->GetIdealCpuCoreIndex();
m_ptrThread_ImgProcess01 = new std::thread(std::bind(&DataInject::ThreadEntry, &DataInject::ThreadFun_ImgProcessData01, (void*)this));
SetThreadAffinityMask(m_ptrThread_ImgProcess01->native_handle(), pow(2, coreIndex));
m_uiCpuCoreIndexUsedMap.insert(m_ptrThread_ImgProcess01->native_handle(), coreIndex);
qDebug() << "m_ptrThread_ImgProcess01 : bind " << QString::number(coreIndex) ;
//
coreIndex = m_pParent->GetIdealCpuCoreIndex();
m_ptrThread_ImgProcess02 = new std::thread(std::bind(&DataInject::ThreadEntry, &DataInject::ThreadFun_ImgProcessData02, (void*)this));
SetThreadAffinityMask(m_ptrThread_ImgProcess02->native_handle(), pow(2, coreIndex));
m_uiCpuCoreIndexUsedMap.insert(m_ptrThread_ImgProcess02->native_handle(), coreIndex);
return true;
}
void DataInject::StopThread_InjectData()
{
if (m_bInjectThreadRunning)
{
m_pParent->ResetUsedCpuCoreIndex(m_uiCpuCoreIndexUsedMap.value(m_ptrThread_InjectData->native_handle()));
m_uiCpuCoreIndexUsedMap.remove(m_ptrThread_InjectData->native_handle());
m_bInjectThreadRunning = false;
m_ptrThread_InjectData->join();
delete m_ptrThread_InjectData;
m_ptrThread_InjectData = nullptr;
}
}
void DataInject::StopThread_ImgProcessData()
{
if (m_bImgProcessThreadRunning)
{
m_bImgProcessThreadRunning = false;
m_pParent->ResetUsedCpuCoreIndex(m_uiCpuCoreIndexUsedMap.value(m_ptrThread_ImgProcess01->native_handle()));
qDebug() << "m_ptrThread_ImgProcess01 : remove bind " << QString::number(m_uiCpuCoreIndexUsedMap.value(m_ptrThread_ImgProcess01->native_handle())) ;
m_uiCpuCoreIndexUsedMap.remove(m_ptrThread_ImgProcess01->native_handle());
m_pParent->ResetUsedCpuCoreIndex(m_uiCpuCoreIndexUsedMap.value(m_ptrThread_ImgProcess02->native_handle()));
m_uiCpuCoreIndexUsedMap.remove(m_ptrThread_ImgProcess02->native_handle());
m_ptrThread_ImgProcess01->join();
m_ptrThread_ImgProcess02->join();
delete m_ptrThread_ImgProcess01;
delete m_ptrThread_ImgProcess02;
m_ptrThread_ImgProcess01 = nullptr;
m_ptrThread_ImgProcess02 = nullptr;
}
}
void DataInject::ThreadFun_FetchRawFileData(int distribute)
{
byte* pReadData = new byte[DefaultMaxImageSize];
int nRes = 0;
int channelIndexStart, channelIndexEnd;
if (distribute == 0)
{
channelIndexStart = 0;
channelIndexEnd = CaptureChannelNum / 2;
}
else if (distribute == 1)
{
channelIndexStart = CaptureChannelNum / 2;
channelIndexEnd = CaptureChannelNum;
}
while (m_bDealRawThreadRunning)
{
for (int i = channelIndexStart; i < channelIndexEnd; i++)
{
if (m_pFileStreamMap.value(i) && m_pInjectDataQueueMap.value(i))
{
// qDebug() << ">>>>>>>Chann>>> " << QString::number(i) << " " << CurrentTime() ;
if ((m_pInjectDataQueueMap.value(i)->Size() >= (DEFAULT_QUEUE_SIZE - 1)))
{
continue;
}
GCycleQueue& varQueueFrameData = m_pFileStreamMap.value(i)->GetFrameQueue();
pReadData = varQueueFrameData.GetFrontPoint();
if ((pReadData != NULL) && m_pInjectDataQueueMap.value(i) && m_varImgDisplayDataQueueMap.value(i))
{
if (m_bIsInjectParamSimulateMap.value(i)) //将模拟构造热像参数行叠加在注入数据尾部
{
uint byteHeadIndex = GetByteOfPixel(m_frameFormatMap.value(i).ePT) * m_frameFormatMap.value(i).nImageWidth *
(m_frameFormatMap.value(i).nImageHeight + m_frameFormatMap.value(i).nParamLineCount) ;
memcpy(pReadData + byteHeadIndex, &m_varThermalImgParamsMap.value(i), sizeof(THERMAL_IMG_PARAMS)); //模拟热像参数行帧头部分
//模拟热像参数行帧尾部分
char szBackBuff[8];
szBackBuff[0] = 0x5a;
szBackBuff[1] = 0x5a;
szBackBuff[2] = 0xa5;
szBackBuff[3] = 0xa5;
szBackBuff[4] = 0xbc;
szBackBuff[5] = 0xbc;
szBackBuff[6] = 0x52;
szBackBuff[7] = 0x5a;
uint byteBackIndex = byteHeadIndex + m_frameFormatMap.value(i).nImageWidth * GetByteOfPixel(m_frameFormatMap.value(i).ePT);
memcpy(pReadData + byteBackIndex - 8, szBackBuff, sizeof(szBackBuff));//模拟热像参数行帧尾部分
}
// qDebug() << ">>>>>>>Chann " << QString::number(i) << " " << CurrentTime() ;
if (m_pInjectDataQueueMap.value(i))
{
m_pInjectDataQueueMap.value(i)->PushBack(pReadData, m_iInjectFrameTotalSizeMap.value(i), nRes);
}
if (m_varImgDisplayDataQueueMap.value(i))
{
m_varImgDisplayDataQueueMap.value(i)->PushBack(pReadData, m_iVideoFileFrameSizeMap.value(i), nRes);
}
}
}
}
SleepAccurate(1);
}
}
static int verbose_msg(const char* const fmt, ...)
{
int ret = 0;
va_list args;
if (1)
{
va_start(args, fmt);
ret = vprintf(fmt, args);
va_end(args);
}
return ret;
}
static BYTE* allocate_buffer(size_t size, size_t alignment)
{
if (size == 0)
{
size = 4;
}
if (alignment == 0)
{
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
alignment = sys_info.dwPageSize;
}
verbose_msg("Allocating host-side buffer of size %llu, aligned to %llu bytes\n", size, alignment);
return (BYTE*)_aligned_malloc(size, alignment);
}
void DataInject::ThreadFun_InjectData()
{
timeBeginPeriod(1);
byte* pInjectFrameData = NULL;
// byte* pCaptureFrameData = new byte[1920 * 1080 * 4 + 4096];
bool bIsLastFrameInjectSuccess = true; //上一帧是否注入成功
QString strLog = QString("");
while (m_bInjectThreadRunning)
{
for (int channelIndex = 0; channelIndex < InjectChannelNum; channelIndex++)
{
if (m_bIsStartInjectMap.value(channelIndex) && m_pInjectDataQueueMap.value(channelIndex))
{
int n = m_uiHostWriteBuffNoMap.value(channelIndex) + 1 ;
int endBuffIndex = m_uiHostWriteBuffNoMap.value(channelIndex) + 2 ;//1 + ChannelCacheNum;
for (; n < endBuffIndex; n++)
{
uint uiRealBuffNo = n % ChannelCacheNum;
uint iOUTPUT_BUFFERn_STATUS = Pcie_ReadReg(InjectChannelRegBaseAddr + (channelIndex * 0x1000) + (0x100 + uiRealBuffNo * 0x10 + 0x8));
if ((iOUTPUT_BUFFERn_STATUS & 0x0F) == 0) //低4bit,bit0~bit3 = 0代表当前缓存是否处于空闲状态
{
if (m_pInjectDataQueueMap.value(channelIndex))
{
pInjectFrameData = m_pInjectDataQueueMap.value(channelIndex)->GetFrontPoint();
if (pInjectFrameData != NULL)
{
//02.上位机对注入数据构造帧编号
uint frameNoGenerate = m_uiInjectFrameNoGenerateMap.value(channelIndex);
switch (GetByteOfPixel(m_frameFormatMap.value(channelIndex).ePT))
{
case 1:
pInjectFrameData[0] = frameNoGenerate;
break;
case 2:
pInjectFrameData[0] = frameNoGenerate;
pInjectFrameData[1] = frameNoGenerate >> 8;
break;
case 3:
pInjectFrameData[0] = frameNoGenerate;
pInjectFrameData[1] = frameNoGenerate >> 8;
pInjectFrameData[2] = frameNoGenerate >> 16;
break;
default:
break;
}
m_uiInjectFrameNoGenerateMap.insert(channelIndex, frameNoGenerate + 1);
}
else
{
break; //退出内层for循环
}
}
uint captureFinalAddr = 0x40000000; //1GB(采集占用DDR前面1GB注入占用DDR后面1GB)
//注入的buff的DDR绝对地址
uint injectCacheAddr = captureFinalAddr + channelIndex * ChannelCacheNum * PcieDDR_EachBuffSize + uiRealBuffNo * PcieDDR_EachBuffSize; //采集卡DDR中缓存区绝对地址(首地址)
//注入的buff的状态寄存器地址
uint injectBuffRegAddr = InjectChannelRegBaseAddr + (channelIndex * 0x1000) + (0x100 + uiRealBuffNo * 0x10 + 0x8);
//01.开始写之前先将buffer状态置为"正在写入" bit0~bit3 = 0x01
iOUTPUT_BUFFERn_STATUS = 0;
iOUTPUT_BUFFERn_STATUS = iOUTPUT_BUFFERn_STATUS & (0xFD); //将bit1置为0 其他bit不变
iOUTPUT_BUFFERn_STATUS = iOUTPUT_BUFFERn_STATUS | ((int)pow(2, 0)); //将bit0置为1 其他bit不变
Pcie_WriteReg(injectBuffRegAddr, (uchar*)&iOUTPUT_BUFFERn_STATUS);
//03.注入数据
bIsLastFrameInjectSuccess = Pcie_WriteData(injectCacheAddr, m_iInjectFrameTotalSizeMap.value(channelIndex), pInjectFrameData);
// qDebug() << QDateTime::currentDateTime().toString("yyyyMMdd hhmmss.zzz ") << " Inject img Data----->: " << ShowHex((char*)pInjectFrameData, 100) + "\n";
//04.注入完成先将buffer状态置为"写入完成" bit0~bit3 = 0x02
iOUTPUT_BUFFERn_STATUS = 0;
iOUTPUT_BUFFERn_STATUS = iOUTPUT_BUFFERn_STATUS | ((int)pow(2, 4)); //将bit4置为1 其他bit不变
iOUTPUT_BUFFERn_STATUS = iOUTPUT_BUFFERn_STATUS | ((int)pow(2, 1)); //将bit1置为1 其他bit不变
iOUTPUT_BUFFERn_STATUS = iOUTPUT_BUFFERn_STATUS & (0xFE); //将bit0置为0 其他bit不变
Pcie_WriteReg(injectBuffRegAddr, (uchar*)&iOUTPUT_BUFFERn_STATUS);
//04.OUTPUT_BUFFERn_WR_SIZE 寄存器中的 buffer_wr_size 设置为已写入缓存的数据长度
uint uiCacheImgSize = m_iDDRBufferCacheSizeMap.value(channelIndex);
Pcie_WriteReg(InjectChannelRegBaseAddr + (channelIndex * 0x1000) + (0x100 + uiRealBuffNo * 0x10 + 0x4), (uchar*)&uiCacheImgSize);
m_uiHostWriteBuffNoMap.insert(channelIndex, uiRealBuffNo);
//注入帧率计算
CalcuImgFps(channelIndex);
}
else
{
break;
}
}
}
}
}
timeEndPeriod(1);
}
void DataInject::ThreadFun_ImgProcessData01()
{
timeBeginPeriod(1);
byte* szY8Data = new byte[MaxImgHeight * MaxImgWidth + 4096];
byte* pProcessFrameData = NULL;
while (m_bImgProcessThreadRunning)
{
for (int channelIndex = 0; channelIndex < (InjectChannelNum / 2); channelIndex ++)
{
if ((!m_varImgDisplayDataQueueMap.value(channelIndex)) || (!m_bIsStartInjectMap.value(channelIndex)))
{
SleepAccurate(1);
continue;
}
pProcessFrameData = m_varImgDisplayDataQueueMap.value(channelIndex)->GetFrontPoint();
if (pProcessFrameData == NULL)
{
continue;
}
QImage nCombineImg;
if (m_frameFormatMap.value(channelIndex).ePT == ePT_Y16) //Y16
{
GdImageLib::Map16BitTo8Bit_u((unsigned char*)m_szY8ImgData_Thread01, (ushort*)pProcessFrameData, (m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount)
* m_frameFormatMap.value(channelIndex).nImageWidth);
nCombineImg = QImage((unsigned char*)m_szY8ImgData_Thread01, m_frameFormatMap.value(channelIndex).nImageWidth,
m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount
, QImage::Format_Indexed8);
nCombineImg.setColorTable(m_varColorTable[0]);
nCombineImg = nCombineImg.convertToFormat(QImage::Format_RGBA8888);
}
else if (m_frameFormatMap.value(channelIndex).ePT == ePT_Y16Y8) //Y16+Y8
{
int pixalNum = (m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount)
* m_frameFormatMap.value(channelIndex).nImageWidth;
for (int i = 0; i < pixalNum; i++)
{
szY8Data[i] = pProcessFrameData[i * 3 + 2]; //取出Y8数据
}
nCombineImg = QImage((unsigned char*)szY8Data, m_frameFormatMap.value(channelIndex).nImageWidth,
m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount,
QImage::Format_Indexed8);
nCombineImg.setColorTable(m_varColorTable[0]);
nCombineImg = nCombineImg.convertToFormat(QImage::Format_RGBA8888);
}
else if (m_frameFormatMap.value(channelIndex).ePT == ePT_Y8) //Y8
{
nCombineImg = QImage((unsigned char*)pProcessFrameData, m_frameFormatMap.value(channelIndex).nImageWidth,
m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount, QImage::Format_Indexed8);
nCombineImg.setColorTable(m_varColorTable[0]);
nCombineImg = nCombineImg.convertToFormat(QImage::Format_RGBA8888);
}
else if (m_frameFormatMap.value(channelIndex).ePT == ePT_YUV422) //YUV422
{
GdImageLib::Convert(m_szRGBAImgData_Thread01, AV_PIX_FMT_RGBA, m_frameFormatMap.value(channelIndex).nImageWidth, m_frameFormatMap.value(channelIndex).nImageHeight, pProcessFrameData, AV_PIX_FMT_UYVY422, m_frameFormatMap.value(channelIndex).nImageWidth, m_frameFormatMap.value(channelIndex).nImageHeight);
nCombineImg = QImage((unsigned char*)m_szRGBAImgData_Thread01, m_frameFormatMap.value(channelIndex).nImageWidth, m_frameFormatMap.value(channelIndex).nImageHeight, QImage::Format_RGBA8888);
}
else if (m_frameFormatMap.value(channelIndex).ePT == ePT_BGR24)
{
GdImageLib::Convert(m_szRGBAImgData_Thread01, AV_PIX_FMT_RGBA, m_frameFormatMap.value(channelIndex).nImageWidth, m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount,
pProcessFrameData, AV_PIX_FMT_BGR24, m_frameFormatMap.value(channelIndex).nImageWidth, m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount);
nCombineImg = QImage((unsigned char*)m_szRGBAImgData_Thread01, m_frameFormatMap.value(channelIndex).nImageWidth,
m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount, QImage::Format_RGBA8888);
}
if (!m_bIsHiddenOsd)
{
QPainter painter(&nCombineImg);
// int GLWidth = m_pOpenGlMap.value(channelIndex)->width();
QFont font ;
int fontsize = m_frameFormatMap.value(channelIndex).nImageWidth / 20; //GLWidth / 2.5;
font.setPixelSize(fontsize);
font.setFamily("Microsoft YaHei");
font.setBold(true);
painter.setFont(font);
painter.setPen(QPen(Qt::green, fontsize, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter.drawText(10, fontsize, QString("%1fps").arg(m_dInjectFrameRateMap.value(channelIndex), 0, 'f', 2));
painter.end();
}
if (m_pOpenGlMap.value(channelIndex))
{
m_pOpenGlMap.value(channelIndex)->UpdateImageData(nCombineImg.bits() /*m_dInjectFrameRate*/);
}
if (m_pFullScreenOpenGlMap.value(channelIndex) && m_pFullScreenOpenGlMap.value(channelIndex)->isVisible())
{
m_pFullScreenOpenGlMap.value(channelIndex)->UpdateImageData(nCombineImg.bits() /*m_dInjectFrameRate*/);
}
}
SleepAccurate(40);
}
timeEndPeriod(1);
}
void DataInject:: ThreadFun_ImgProcessData02()
{
timeBeginPeriod(1);
byte* pProcessFrameData = NULL;
byte* szY8Data = new byte[MaxImgHeight * MaxImgWidth + 4096];
while (m_bImgProcessThreadRunning)
{
for (int channelIndex = (InjectChannelNum / 2); channelIndex < InjectChannelNum; channelIndex ++)
{
if ((!m_varImgDisplayDataQueueMap.value(channelIndex)) || (!m_bIsStartInjectMap.value(channelIndex)))
{
SleepAccurate(1);
continue;
}
pProcessFrameData = m_varImgDisplayDataQueueMap.value(channelIndex)->GetFrontPoint();
if (pProcessFrameData == NULL)
{
continue;
}
QImage nCombineImg;
if (m_frameFormatMap.value(channelIndex).ePT == ePT_Y16) //Y16 YUV422 Y16+Y8
{
GdImageLib::Map16BitTo8Bit_u((unsigned char*)m_szY8ImgData_Thread02, (ushort*)pProcessFrameData,
(m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount)
* m_frameFormatMap.value(channelIndex).nImageWidth);
nCombineImg = QImage((unsigned char*)m_szY8ImgData_Thread02, m_frameFormatMap.value(channelIndex).nImageWidth,
m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount,
QImage::Format_Indexed8);
nCombineImg.setColorTable(m_varColorTable[0]);
nCombineImg = nCombineImg.convertToFormat(QImage::Format_RGBA8888);
}
else if (m_frameFormatMap.value(channelIndex).ePT == ePT_Y16Y8) //Y16+Y8
{
int pixalNum = (m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount)
* m_frameFormatMap.value(channelIndex).nImageWidth;
for (int i = 0; i < pixalNum; i++)
{
szY8Data[i] = pProcessFrameData[i * 3 + 2]; //取出Y8数据
}
nCombineImg = QImage((unsigned char*)szY8Data, m_frameFormatMap.value(channelIndex).nImageWidth,
m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount,
QImage::Format_Indexed8);
nCombineImg.setColorTable(m_varColorTable[0]);
nCombineImg = nCombineImg.convertToFormat(QImage::Format_RGBA8888);
}
else if (m_frameFormatMap.value(channelIndex).ePT == ePT_Y8) //Y8
{
nCombineImg = QImage((unsigned char*)pProcessFrameData, m_frameFormatMap.value(channelIndex).nImageWidth,
m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount,
QImage::Format_Indexed8);
nCombineImg.setColorTable(m_varColorTable[0]);
nCombineImg = nCombineImg.convertToFormat(QImage::Format_RGBA8888);
}
else if (m_frameFormatMap.value(channelIndex).ePT == ePT_YUV422) //YUV422
{
GdImageLib::Convert(m_szRGBAImgData_Thread02, AV_PIX_FMT_RGBA, m_frameFormatMap.value(channelIndex).nImageWidth, m_frameFormatMap.value(channelIndex).nImageHeight, pProcessFrameData, AV_PIX_FMT_UYVY422, m_frameFormatMap.value(channelIndex).nImageWidth, m_frameFormatMap.value(channelIndex).nImageHeight);
nCombineImg = QImage((unsigned char*)m_szRGBAImgData_Thread02, m_frameFormatMap.value(channelIndex).nImageWidth, m_frameFormatMap.value(channelIndex).nImageHeight, QImage::Format_RGBA8888);
}
else if (m_frameFormatMap.value(channelIndex).ePT == ePT_BGR24)
{
GdImageLib::Convert(m_szRGBAImgData_Thread02, AV_PIX_FMT_RGBA, m_frameFormatMap.value(channelIndex).nImageWidth,
m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount,
pProcessFrameData, AV_PIX_FMT_BGR24, m_frameFormatMap.value(channelIndex).nImageWidth,
m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount);
nCombineImg = QImage((unsigned char*)m_szRGBAImgData_Thread02, m_frameFormatMap.value(channelIndex).nImageWidth,
m_frameFormatMap.value(channelIndex).nImageHeight + m_frameFormatMap.value(channelIndex).nParamLineCount,
QImage::Format_RGBA8888);
}
if (!m_bIsHiddenOsd)
{
QPainter painter(&nCombineImg);
// int GLWidth = m_pOpenGlMap.value(channelIndex)->width();
QFont font;
int fontsize = m_frameFormatMap.value(channelIndex).nImageWidth / 20; //GLWidth / 2.5;
font.setPixelSize(fontsize);
font.setFamily("Microsoft YaHei");
font.setBold(true);
painter.setFont(font);
painter.setPen(QPen(Qt::green, fontsize, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter.drawText(10, fontsize, QString("%1fps").arg(m_dInjectFrameRateMap.value(channelIndex), 0, 'f', 2));
painter.end();
}
if (m_pOpenGlMap.value(channelIndex))
{
m_pOpenGlMap.value(channelIndex)->UpdateImageData(nCombineImg.bits() /*m_dInjectFrameRate*/);
}
if (m_pFullScreenOpenGlMap.value(channelIndex) && m_pFullScreenOpenGlMap.value(channelIndex)->isVisible())
{
m_pFullScreenOpenGlMap.value(channelIndex)->UpdateImageData(nCombineImg.bits() /*m_dInjectFrameRate*/);
}
}
SleepAccurate(40);
}
timeEndPeriod(1);
}
void DataInject::ThreadFun_WriteCmdControlData()
{
while (m_bWriteCmdThreadRunning)
{
for (int channelIndex = 0; channelIndex < InjectChannelNum; channelIndex++)
{
if (!m_varInjectCMDMap.value(channelIndex))
{
continue;
}
uint uiCmdDataSize = m_varInjectCMDMap.value(channelIndex)->Size();
if (uiCmdDataSize > 0)
{
QString strWriteLog = QString("");
uint uiCMDInjectStatus = Pcie_ReadReg((InjectChannelRegBaseAddr + channelIndex * 0x1000) + 0x028); //判断FPGA是否准备好
QString regAddr = QString::number((InjectChannelRegBaseAddr + channelIndex * 0x1000) + 0x028, 16) ;
qDebug() << "0x028" << regAddr << "uiCMDInjectStatus: " << QString::number(uiCMDInjectStatus);
if (((uiCMDInjectStatus >> 10) & 0x01) == 0) // bit10为0 代表空闲
{
char* pCmdData = m_varInjectCMDMap.value(channelIndex)->PopData();
uint iTotalDataSize = uiCmdDataSize;
uint iTotalSendTimes = iTotalDataSize / 4; //总发送次数
if ((iTotalDataSize % 4) != 0)
{
iTotalSendTimes++;
}
for (int iCurrSendTimes = 1; iCurrSendTimes <= iTotalSendTimes; iCurrSendTimes++)
{
uint uiDataBytes = 4;
//空闲,则写入控制命令
Pcie_WriteRegCmdData(InjectChannelRegBaseAddr + (channelIndex * 0x1000) + 0x400 + (iCurrSendTimes - 1) * 4, (uchar*)(pCmdData + 4 * (iCurrSendTimes - 1)), uiDataBytes);
qDebug() << "Reg Addr: " << QString::number(0x400 + (iCurrSendTimes - 1) * 4, 16) << "Data: " << ShowHex((char*)(pCmdData + 4 * (iCurrSendTimes - 1)), uiDataBytes) ;
strWriteLog += " Reg Addr: " + QString::number(InjectChannelRegBaseAddr + (channelIndex * 0x1000) + 0x400 + (iCurrSendTimes - 1))
+ " Write Data: " + ShowHex((char*)(pCmdData + 4 * (iCurrSendTimes - 1)), uiDataBytes);
if (m_pCmdInjectLogMap.value(channelIndex))
{
m_pCmdInjectLogMap.value(channelIndex)->addLog(strWriteLog.toUtf8().data());
}
}
//设置注入命令数据长度
uint iCMDStatus = uiCmdDataSize - 1; //bit0~bit9为(数据长度-1)
//设置写入状态为CPU已写入
iCMDStatus |= ((int)pow(2, 10)); //bit10 置为1 代表CPU已写入
Pcie_WriteReg(InjectChannelRegBaseAddr + (channelIndex * 0x1000) + 0x028, (uchar*)&iCMDStatus);
qDebug() << "发送成功!";
}
else
{
qDebug() << "未空闲!";
}
}
}
SleepAccurate(1);
}
}
void DataInject::ThreadEntry(DataInject::ThreadRunFunPtr pRunFun, void* pOwner)
{
DataInject* pRunClass = reinterpret_cast<DataInject*>(pOwner);
if (nullptr == pRunClass)
{
return;
}
(pRunClass->*pRunFun)();
}
QString DataInject::ShowHex(char* str, int length)
{
QString strsss = "";
for (int i = 0; i < length; i++)
{
char outChar = str[i];
strsss += QString("%1").arg(outChar & 0xFF, 2, 16, QLatin1Char('0')).toUpper() + QString(" ");
}
return strsss;
}
void DataInject::InjectThreadEntry(InjectThreadRunFunPtr pRunFun, void* pOwner, int channelIndex)
{
DataInject* pRunClass = reinterpret_cast<DataInject*>(pOwner);
if (nullptr == pRunClass)
{
return;
}
(pRunClass->*pRunFun)(channelIndex);
}
QString DataInject::CurrentTime()
{
return QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
}
inline void DataInject::SleepAccurate(int milliseconds)
{
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
// QEventLoop loop;
// QTimer::singleShot(milliseconds, &loop, &QEventLoop::quit);
// loop.exec();
}