284 lines
10 KiB
C++
284 lines
10 KiB
C++
/**
|
||
*该类用于与Xilinx FPGA芯片(K7) XDMA框架进行交互
|
||
*
|
||
*/
|
||
|
||
|
||
#ifndef DATACAPTURE_H
|
||
#define DATACAPTURE_H
|
||
|
||
#include <QObject>
|
||
#include <QFuture>
|
||
#include <QThreadPool>
|
||
#include <QtConcurrent/QtConcurrent>
|
||
|
||
#include "./XDmaCommDef.h"
|
||
#include "./PcieFun.h"
|
||
#include "./GIOParams.h"
|
||
|
||
#include <iostream>
|
||
#include <atomic>
|
||
#include <thread>
|
||
|
||
|
||
class Device_File
|
||
{
|
||
public:
|
||
Device_File::Device_File() : h(INVALID_HANDLE_VALUE) {}
|
||
|
||
|
||
std::string get_windows_error_msg()
|
||
{
|
||
char msg_buffer[256];
|
||
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
|
||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg_buffer, 256, NULL);
|
||
return{ msg_buffer, 256 };
|
||
}
|
||
|
||
Device_File(const std::string& path, DWORD accessFlags)
|
||
{
|
||
size_t size = path.length();
|
||
wchar_t* buffer = new wchar_t[size + 1];
|
||
MultiByteToWideChar(CP_ACP, 0, path.c_str(), size, buffer, size * sizeof(wchar_t));
|
||
buffer[size] = 0; //确保以 '\0' 结尾
|
||
qDebug() << QString::fromWCharArray(buffer) ;
|
||
h = CreateFile(buffer, accessFlags, 0, NULL, OPEN_EXISTING,
|
||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||
if (h == INVALID_HANDLE_VALUE)
|
||
{
|
||
QString errorStr = "Event: Opening device Event file failed: " ;
|
||
qDebug() << errorStr;
|
||
std::cout << "error: " << get_windows_error_msg() << std::endl;
|
||
}
|
||
delete buffer;
|
||
buffer = NULL;
|
||
}
|
||
|
||
~Device_File()
|
||
{
|
||
if (h != INVALID_HANDLE_VALUE)
|
||
{
|
||
CloseHandle(h);
|
||
h = INVALID_HANDLE_VALUE;
|
||
}
|
||
}
|
||
|
||
template <typename T>
|
||
T read(long address)
|
||
{
|
||
T buffer;
|
||
if (INVALID_SET_FILE_POINTER == SetFilePointer(h, address, NULL, FILE_BEGIN))
|
||
{
|
||
std::string errorStr = get_windows_error_msg();
|
||
std::cout << "errorStr001: " << errorStr << std::endl;
|
||
return buffer;
|
||
}
|
||
unsigned long num_bytes_read;
|
||
if (!ReadFile(h, &buffer, sizeof(T), &num_bytes_read, NULL))
|
||
{
|
||
std::string errorStr = "read : Failed to read from stream! " /*+ get_windows_error_msg()*/;
|
||
qDebug() << QString::fromStdString(errorStr);
|
||
return buffer;
|
||
}
|
||
else if (num_bytes_read != sizeof(T))
|
||
{
|
||
qDebug() << "read : Failed to read all bytes!";
|
||
return buffer;
|
||
}
|
||
return buffer;
|
||
}
|
||
|
||
int write(long address, DWORD size, BYTE* buffer)
|
||
{
|
||
if (INVALID_SET_FILE_POINTER == SetFilePointer(h, address, NULL, FILE_BEGIN))
|
||
{
|
||
// std::string errorStr = "write : SetFilePointer failed: " /*+ get_windows_error_msg()*/;
|
||
// qDebug() << QString::fromStdString(errorStr);
|
||
}
|
||
unsigned long wr_size;
|
||
if (!WriteFile(h, (void*)(buffer), (DWORD)(size), &wr_size, NULL))
|
||
{
|
||
// std::string errorStr = "write : Failed to read from stream! "/* + get_windows_error_msg()*/;
|
||
// qDebug() << QString::fromStdString(errorStr);
|
||
}
|
||
else if (wr_size != size)
|
||
{
|
||
// qDebug() << "write : Failed to write all bytes!";
|
||
}
|
||
return wr_size;
|
||
}
|
||
|
||
private:
|
||
HANDLE h;
|
||
};
|
||
|
||
|
||
typedef void (*SystemStateCallback)(uint channelIndex, const QByteArray& state, void* userData);
|
||
|
||
typedef void (*pCallbackFunc_OnCaptrueData)(uint8_t* pData, uint32_t nDataSize, uint32_t nChannelIndex, void* pOwner);
|
||
|
||
class DataCapture : public QObject
|
||
{
|
||
Q_OBJECT
|
||
public:
|
||
explicit DataCapture(QObject* parent = nullptr, char* device_base_path = nullptr);
|
||
virtual ~DataCapture();
|
||
|
||
/**********************主要接口*****************************/
|
||
/**
|
||
* @brief 设置采集回调函数
|
||
*/
|
||
void SetCaptureCallback(pCallbackFunc_OnCaptrueData pCallbackFunc_CaptrueData, void* pOwner);
|
||
|
||
/**
|
||
* @brief 开始采集
|
||
*/
|
||
void StartCapture(GFrameFormat* captureParam, void* openglview = nullptr);
|
||
|
||
|
||
/**
|
||
* @brief 停止采集
|
||
*/
|
||
void StopCapture(int channelIndex);
|
||
|
||
|
||
/**
|
||
* @brief 通过设置回调来获取每路光纤端口的系统状态数据,与 StartCapture() 接口独立。
|
||
*/
|
||
void SetSystemStatusCallback(int channelIndex, SystemStateCallback callback, void* user, bool isOpen);
|
||
|
||
|
||
/**********************下面为非必要接口*****************************/
|
||
/**
|
||
* @brief 获取延时信息 返回结构体
|
||
*/
|
||
CaptureDelayStatusInfo* GetDelayStatus(int channelIndex);
|
||
|
||
/**
|
||
* @brief 开启上位机发送图像数据到显卡→显卡在屏幕上绘制出对应图像数据的耗时
|
||
*/
|
||
void SetImgDisplayDelayTest(int channelIndex, bool isStart);
|
||
|
||
/**
|
||
* @brief 是否正在采集数据
|
||
* @return
|
||
*/
|
||
bool IsCapture(int channelIndex)
|
||
{
|
||
return m_bIsStartCaptureMap.value(channelIndex);
|
||
}
|
||
|
||
/**
|
||
* @brief SetFullScreenWgt 设置全屏播放的控件
|
||
* @param channelIndex 端口号
|
||
* @param fullScreenOpenglview 全屏播放的控件
|
||
*/
|
||
void SetFullScreenWgt(int channelIndex = -1, void* fullScreenOpenglview = nullptr);
|
||
|
||
|
||
void SetOsdHidden(bool isHidden) {m_bIsHiddenOsd = isHidden ; }
|
||
void SetShowErrorFrame(bool isShow) {m_bIsShowErrorFrame = isShow ; }
|
||
|
||
private slots:
|
||
void OnSlotCaptureCmdDataTimeOut();
|
||
|
||
private:
|
||
QString ShowHex(char* str, int length); //Hex to String
|
||
int GetByteOfPixel(ePixelType ePT);
|
||
|
||
typedef void (DataCapture::*ThreadRunFunPtr)();
|
||
static void ThreadEntry(ThreadRunFunPtr pRunFun, void* pOwner);
|
||
|
||
typedef void (DataCapture::*ReadEventThreadRunFunPtr)(int channelIndex);
|
||
static void ThreadEntry_ReadEvent(ReadEventThreadRunFunPtr pRunFun, void* pOwner, int channelIndex);
|
||
|
||
//1.数据采集处理线程
|
||
bool StartThread_CaptureDeviceData();
|
||
void StopThread_CaptureDeviceData();
|
||
void ThreadFun_CaptureDeviceData();
|
||
|
||
//2.系统状态线程
|
||
void ThreadFun_GetSysStates(); //命令采集
|
||
|
||
//3.中断通知读取线程
|
||
void StartThread_DealInterEvent(int channelIndex);
|
||
void StopThread_DealInterEvent(int channelIndex);
|
||
void ThreadFun_ReadInterEvent(int channelIndex);
|
||
|
||
|
||
qint64 CurrentTime();
|
||
inline void SleepAccurate(int milliseconds);
|
||
|
||
//设备数据采集线程
|
||
bool m_bThreadRunning_CaptureDevice;
|
||
std::thread* m_ptrThread_CaptureDevice;
|
||
|
||
|
||
bool m_bGetSysStatesThreadRuning; //获取系统状态
|
||
std::thread* m_ptrThread_GetSysStates;
|
||
//***************************************
|
||
|
||
|
||
//显示控件
|
||
QMap<int, GFrameFormat> m_frameFormatMap; //key: 通道号 value:图像格式
|
||
QMap<int, int > m_iFrameSizeMap; //key: 通道号 value: 每路对应的帧size
|
||
QMap<int, Device_File*> m_pInterEventMap; // key: 通道号 value: 中断事件对应Map
|
||
QMap<int, unsigned char*> m_pCaptureBuffMap; //key: 通道号 value: 采集buff缓存Map
|
||
QMap<int, bool> m_bIsStartCaptureMap; //key: 通道号 value:是否开始采集状态
|
||
QMap<int, int> m_uiHostReadBuffNoMap; //key: 通道号 value: 上位机在上一个循环中最后读到的BuffNo索引值 取值: 0~(ChannelCacheNum-1)
|
||
QMap<int, uint> m_uiCaptureFrameNoMap; //key: 通道号 value: 采集的当前帧编号
|
||
QMap<int, uint> m_uiCaptureLossFrameNoMap; //key: 通道号 value: 采集丢帧数统计
|
||
QMap<int, DynamicArray*> m_varCaptureCMDMap; // /key: ChannelIndex value:动态数组 命令采集
|
||
|
||
//帧率计算
|
||
QMap<int, uint> m_uiCurrFrameRateCountMap; //key: 通道号 value:当前帧数
|
||
QMap<int, int64_t> m_iFrameTimeStartMap; //key: 通道号 value:开始统计的时间戳
|
||
QMap<int, uint> m_uiCalcuFramesMap; //key: 通道号 value: 多少帧数计算一次 100
|
||
QMap<int, double> m_dCaptureFrameRateMap; //key: 通道号 value:采集帧率
|
||
QMap<int, int> m_iHostDealImgToDrawMap; //key: 通道号 value: 上位机从采集到图像到处理完,调用显卡绘制接口开始进行绘制的时间 单位:毫秒
|
||
QMap<int, bool> m_bStartImgDisplayDelayMap; //key: 通道号 value:是否开启上位机发送图像数据到显卡→显卡在屏幕上绘制出对应图像数据的耗时
|
||
QMap<int, ushort> m_iImgDisplayDelayTestIndexMap; //key: 通道号 value: 上位机发送图像数据到显卡→显卡在屏幕上绘制出对应图像数据 显示计数 1-15
|
||
|
||
QMap<int, uint > m_uiMaxFrameNoMap; //key: 通道号 value:每路最大帧编号
|
||
QMap<int, QTimer*> m_varStatusDetectTimerMap; //key: 通道号 value:状态监测定时器
|
||
QMap<int, bool> m_bIsInterEventTimeOutMap; //读取中断数据是否超时
|
||
|
||
//事件中断线程
|
||
QMap<int, bool> m_bEventInterThreadRunningMap; //key:通道号 value:事件中断线程运行状态
|
||
QMap<int, std::thread*> m_ptrThread_EventInterMap; //key:通道号 value:事件中断线程
|
||
QMap<int, SystemStateCallback> m_pFunCallBackMap;
|
||
QMap<int, void*> m_pSysStateUserMap;
|
||
QMap<int, HANDLE> m_pSynEventMap; //key:通道号 value:同步事件
|
||
|
||
uint m_iTestFrameIndex;
|
||
QTimer m_varTestVideoTimer;
|
||
QTimer m_varCaptureCmdDataTimer;
|
||
uint m_iCaptureEnableStatus; //采集使能状态
|
||
std::string m_strDevicePath; //采集卡地址
|
||
|
||
//采集延时状态数组
|
||
CaptureDelayStatusInfo m_szCaptureStatus[ChannelCacheNum];
|
||
|
||
byte* m_szY8ImgData_Thread01;
|
||
byte* m_szRGBAImgData_Thread01;
|
||
|
||
byte* m_szY8ImgData_Thread02;
|
||
byte* m_szRGBAImgData_Thread02;
|
||
// uint m_uiCpuCoreCount;//CPU核心数
|
||
bool m_bIsOpenRecordThread;
|
||
bool m_bIsOpenCaptureThread;
|
||
|
||
uint uiThreadSleepTime; //线程休眠时间
|
||
bool m_bIsHiddenOsd;
|
||
bool m_bIsShowErrorFrame;
|
||
|
||
uint m_uiAXIFrequence = 0;
|
||
QMap<void*, uint> m_uiCpuCoreIndexUsedMap;
|
||
|
||
pCallbackFunc_OnCaptrueData m_pCallbackFunc_OnCaptrueData;
|
||
void* m_pOwner_OnCaptrueData;
|
||
};
|
||
|
||
|
||
#endif // DATACAPTURE_H
|