1121 lines
52 KiB
C++
1121 lines
52 KiB
C++
#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();
|
||
}
|