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

284 lines
10 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.
/**
*该类用于与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