GrabBag/Device/GalaxyDevice/Src/GalaxyDevice.cpp

1281 lines
36 KiB
C++
Raw Normal View History

2025-12-10 00:01:32 +08:00
#include "GalaxyDevice.h"
2025-12-20 16:18:12 +08:00
#include "GalaxySDKManager.h"
2025-12-10 00:01:32 +08:00
#include "VrError.h"
#include "VrLog.h"
2025-12-10 00:01:32 +08:00
#include <cstring>
#include <iostream>
#include <thread>
#include <chrono>
2025-12-10 00:01:32 +08:00
// Galaxy SDK头文件
#ifdef _WIN32
// Windows 平台使用 C++ API
#define _WINSOCKAPI_ // 防止winsock.h被包含避免与winsock2.h冲突
2025-12-10 00:01:32 +08:00
#include "GXIAPIBase.h"
#include "IGXFactory.h"
#include "IGXDevice.h"
#include "IGXStream.h"
#include "IGXFeatureControl.h"
#include "IImageData.h"
#include "IIntFeature.h"
#include "IFloatFeature.h"
#include "IEnumFeature.h"
#include "ICommandFeature.h"
#include "IVrUtils.h"
2025-12-10 00:01:32 +08:00
using namespace GxIAPICPP;
#else
// Linux/ARM 平台使用 C API
#include "GxIAPI.h"
#include "DxImageProc.h"
#endif
// 帧回调处理类实现
#ifdef _WIN32
void CGalaxyDevice::CCaptureEventHandler::DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam)
{
if (m_pDevice && !objImageDataPointer.IsNull())
{
m_pDevice->ProcessCapturedImage(objImageDataPointer);
}
}
#endif
// 创建设备对象
int IGalaxyDevice::CreateObject(IGalaxyDevice** ppDevice)
{
if (ppDevice == nullptr) {
return ERR_CODE(DEV_ARG_INVAILD);
}
try {
*ppDevice = new CGalaxyDevice();
return SUCCESS;
}
catch (...) {
return ERR_CODE(DATA_ERR_MEM);
}
}
// 构造函数
CGalaxyDevice::CGalaxyDevice()
: m_pCaptureEventHandler(nullptr)
, m_bSDKInitialized(false)
, m_bDeviceOpen(false)
, m_bAcquisitioning(false)
, m_bNewImageReady(false)
{
memset(&m_capturedImage, 0, sizeof(m_capturedImage));
#ifdef _WIN32
// Windows 平台初始化
#else
// Linux/ARM 平台初始化
m_hDevice = nullptr;
m_pDeviceInfo = nullptr;
m_nDeviceNum = 0;
#endif
}
// 析构函数
CGalaxyDevice::~CGalaxyDevice()
{
try {
if (m_bAcquisitioning) {
StopAcquisition();
}
if (m_bDeviceOpen) {
CloseDevice();
}
if (m_bSDKInitialized) {
UninitSDK();
}
#ifdef _WIN32
if (m_pCaptureEventHandler) {
delete m_pCaptureEventHandler;
m_pCaptureEventHandler = nullptr;
}
#else
// Linux/ARM 平台清理
if (m_pDeviceInfo) {
delete[] m_pDeviceInfo;
m_pDeviceInfo = nullptr;
}
#endif
}
catch (...) {
// 忽略析构函数中的异常
}
}
// 初始化SDK
int CGalaxyDevice::InitSDK()
{
if (m_bSDKInitialized) {
return SUCCESS;
}
2025-12-20 16:18:12 +08:00
int ret = GalaxySDKManager::GetInstance().InitSDK();
if (ret == SUCCESS) {
2025-12-10 00:01:32 +08:00
m_bSDKInitialized = true;
}
2025-12-20 16:18:12 +08:00
return ret;
2025-12-10 00:01:32 +08:00
}
// 反初始化SDK
int CGalaxyDevice::UninitSDK()
{
if (m_bSDKInitialized) {
2025-12-20 16:18:12 +08:00
int ret = GalaxySDKManager::GetInstance().UninitSDK();
if (ret == SUCCESS) {
m_bSDKInitialized = false;
2025-12-10 00:01:32 +08:00
}
2025-12-20 16:18:12 +08:00
return ret;
2025-12-10 00:01:32 +08:00
}
return SUCCESS;
}
// 获取SDK版本
int CGalaxyDevice::GetSDKVersion(std::string& version)
{
version = "GalaxySDK 1.1.2412.9031";
return SUCCESS;
}
// 枚举设备
int CGalaxyDevice::EnumerateDevices(std::vector<GalaxyDeviceInfo>& deviceList, unsigned int timeout)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (!m_bSDKInitialized) {
return ERR_CODE(DEV_NO_OPEN);
}
deviceList.clear();
// 更新设备列表
gxdeviceinfo_vector vectorDeviceInfo;
IGXFactory::GetInstance().UpdateDeviceList(timeout, vectorDeviceInfo);
// 转换为我们的数据结构
for (size_t i = 0; i < vectorDeviceInfo.size(); ++i) {
GalaxyDeviceInfo info;
info.serialNumber = vectorDeviceInfo[i].GetSN();
info.modelName = vectorDeviceInfo[i].GetModelName();
info.displayName = vectorDeviceInfo[i].GetDisplayName();
info.ipAddress = vectorDeviceInfo[i].GetIP();
info.macAddress = vectorDeviceInfo[i].GetMAC();
info.deviceClass = vectorDeviceInfo[i].GetDeviceClass();
info.width = 0;
info.height = 0;
deviceList.push_back(info);
}
return SUCCESS;
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_NOT_FIND);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_bSDKInitialized) {
return ERR_CODE(DEV_NO_OPEN);
}
deviceList.clear();
// 更新设备列表
GX_STATUS status = GXUpdateDeviceList(&m_nDeviceNum, timeout);
if (status != GX_STATUS_SUCCESS) {
return static_cast<int>(status);
}
LOG_DEBUG("Find galaxy device size : %zd \n", m_nDeviceNum);
2025-12-10 00:01:32 +08:00
if (m_nDeviceNum == 0) {
return ERR_CODE(DEV_NOT_FIND);
2025-12-10 00:01:32 +08:00
}
// 分配设备信息缓存
if (m_pDeviceInfo) {
delete[] m_pDeviceInfo;
}
m_pDeviceInfo = new GX_DEVICE_BASE_INFO[m_nDeviceNum];
size_t nSize = m_nDeviceNum * sizeof(GX_DEVICE_BASE_INFO);
status = GXGetAllDeviceBaseInfo(m_pDeviceInfo, &nSize);
if (status != GX_STATUS_SUCCESS) {
delete[] m_pDeviceInfo;
m_pDeviceInfo = nullptr;
return static_cast<int>(status);
}
// 转换为我们的数据结构
for (uint32_t i = 0; i < m_nDeviceNum; ++i) {
GalaxyDeviceInfo info;
info.serialNumber = m_pDeviceInfo[i].szSN;
info.modelName = m_pDeviceInfo[i].szModelName;
info.displayName = m_pDeviceInfo[i].szDisplayName;
info.ipAddress = ""; // ARM 版本不提供 IP 地址
info.macAddress = ""; // ARM 版本不提供 MAC 地址
// 设备类型ARM 版本使用 deviceClass (enum),需要转换为字符串
switch (m_pDeviceInfo[i].deviceClass) {
case GX_DEVICE_CLASS_U3V:
info.deviceClass = "U3V";
break;
case GX_DEVICE_CLASS_GEV:
info.deviceClass = "GEV";
break;
case GX_DEVICE_CLASS_USB2:
info.deviceClass = "USB2.0";
break;
default:
info.deviceClass = "Unknown";
break;
}
info.width = 0;
info.height = 0;
deviceList.push_back(info);
}
return SUCCESS;
#endif
}
// 通过序列号打开设备
int CGalaxyDevice::OpenDevice(const std::string& serialNumber)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (!m_bSDKInitialized) {
return ERR_CODE(DEV_NO_OPEN);
}
if (m_bDeviceOpen) {
CloseDevice();
}
// 通过序列号打开设备
m_objDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(
gxstring(serialNumber.c_str()),
GX_ACCESS_EXCLUSIVE
);
if (m_objDevicePtr.IsNull()) {
return ERR_CODE(DEV_NOT_FIND);
}
// 打开数据流
m_objStreamPtr = m_objDevicePtr->OpenStream(0);
if (m_objStreamPtr.IsNull()) {
m_objDevicePtr = CGXDevicePointer();
return ERR_CODE(DEV_OPEN_ERR);
}
// 获取远程特性控制
m_objFeatureControlPtr = m_objDevicePtr->GetRemoteFeatureControl();
if (m_objFeatureControlPtr.IsNull()) {
m_objStreamPtr = CGXStreamPointer();
m_objDevicePtr = CGXDevicePointer();
return ERR_CODE(DEV_OPEN_ERR);
}
2025-12-20 16:18:12 +08:00
// 设置采集缓冲区数量为5支持多线程并行取图
CIntFeaturePointer ptrBufferNum = m_objFeatureControlPtr->GetIntFeature("StreamBufferHandlingMode");
if (!ptrBufferNum.IsNull()) {
ptrBufferNum->SetValue(5);
}
2025-12-10 00:01:32 +08:00
m_bDeviceOpen = true;
return SUCCESS;
}
catch (CGalaxyException& e) {
m_objFeatureControlPtr = CGXFeatureControlPointer();
m_objStreamPtr = CGXStreamPointer();
m_objDevicePtr = CGXDevicePointer();
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
m_objFeatureControlPtr = CGXFeatureControlPointer();
m_objStreamPtr = CGXStreamPointer();
m_objDevicePtr = CGXDevicePointer();
return ERR_CODE(DEV_OPEN_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_bSDKInitialized) {
return ERR_CODE(DEV_NO_OPEN);
}
if (m_bDeviceOpen) {
CloseDevice();
}
// 通过序列号打开设备
GX_OPEN_PARAM openParam;
openParam.accessMode = GX_ACCESS_EXCLUSIVE;
openParam.openMode = GX_OPEN_SN;
openParam.pszContent = const_cast<char*>(serialNumber.c_str());
GX_STATUS status = GXOpenDevice(&openParam, &m_hDevice);
if (status != GX_STATUS_SUCCESS) {
m_hDevice = nullptr;
return static_cast<int>(status);
}
2025-12-20 16:18:12 +08:00
// 3. 设置触发模式为连续触发(无需外部触发)
status = GXSetEnum(m_hDevice, GX_ENUM_TRIGGER_MODE, GX_TRIGGER_MODE_OFF);
LOG_DEBUG("Set trigger mode to off %s\n", status == GX_STATUS_SUCCESS ? "success" : "failed");
//使能采集帧率调节模式
status = GXSetEnum(m_hDevice, GX_ENUM_ACQUISITION_FRAME_RATE_MODE, GX_ACQUISITION_FRAME_RATE_MODE_ON);
//设置采集帧率,假设设置为 10.0,用户按照实际需求设置此值
status = GXSetFloat(m_hDevice, GX_FLOAT_ACQUISITION_FRAME_RATE, 5);
LOG_DEBUG("Set acquisition frame rate to 5 %s\n", status == GX_STATUS_SUCCESS ? "success" : "failed");
// 设置数据传输块大小(提高传输性能)
bool bStreamTransferSize = false;
status = GXIsImplemented(m_hDevice, GX_DS_INT_STREAM_TRANSFER_SIZE, &bStreamTransferSize);
if (status == GX_STATUS_SUCCESS && bStreamTransferSize) {
status = GXSetInt(m_hDevice, GX_DS_INT_STREAM_TRANSFER_SIZE, 64 * 1024);
if (status == GX_STATUS_SUCCESS) {
LOG_DEBUG("Set stream transfer size to 64KB\n");
}
}
// 设置数据传输块数量(提高传输性能)
bool bStreamTransferNumberUrb = false;
status = GXIsImplemented(m_hDevice, GX_DS_INT_STREAM_TRANSFER_NUMBER_URB, &bStreamTransferNumberUrb);
if (status == GX_STATUS_SUCCESS && bStreamTransferNumberUrb) {
status = GXSetInt(m_hDevice, GX_DS_INT_STREAM_TRANSFER_NUMBER_URB, 64);
if (status == GX_STATUS_SUCCESS) {
LOG_DEBUG("Set stream transfer number URB to 64\n");
}
}
2025-12-10 00:01:32 +08:00
m_bDeviceOpen = true;
return SUCCESS;
#endif
}
// 通过索引打开设备
int CGalaxyDevice::OpenDeviceByIndex(unsigned int index)
{
try {
// 先枚举设备
std::vector<GalaxyDeviceInfo> deviceList;
int ret = EnumerateDevices(deviceList, 2000);
if (ret != SUCCESS) {
return ret;
}
if (index >= deviceList.size()) {
return ERR_CODE(DEV_ID_ERR);
}
// 通过序列号打开
return OpenDevice(deviceList[index].serialNumber);
}
catch (...) {
return ERR_CODE(DEV_ID_ERR);
}
}
// 关闭设备
int CGalaxyDevice::CloseDevice()
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_bAcquisitioning) {
StopAcquisition();
}
m_objFeatureControlPtr = CGXFeatureControlPointer();
m_objStreamPtr = CGXStreamPointer();
if (!m_objDevicePtr.IsNull()) {
m_objDevicePtr->Close();
m_objDevicePtr = CGXDevicePointer();
}
m_bDeviceOpen = false;
return SUCCESS;
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CLOSE_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (m_bAcquisitioning) {
StopAcquisition();
}
if (m_hDevice) {
GX_STATUS status = GXCloseDevice(m_hDevice);
m_hDevice = nullptr;
m_bDeviceOpen = false;
if (status != GX_STATUS_SUCCESS) {
return static_cast<int>(status);
}
}
m_bDeviceOpen = false;
return SUCCESS;
#endif
}
// 检查设备是否打开
bool CGalaxyDevice::IsDeviceOpen()
{
return m_bDeviceOpen;
}
// 获取设备信息
int CGalaxyDevice::GetDeviceInfo(GalaxyDeviceInfo& deviceInfo)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (!m_bDeviceOpen || m_objDevicePtr.IsNull()) {
return ERR_CODE(DEV_NO_OPEN);
}
const CGXDeviceInfo& info = m_objDevicePtr->GetDeviceInfo();
deviceInfo.serialNumber = info.GetSN();
deviceInfo.modelName = info.GetModelName();
deviceInfo.displayName = info.GetDisplayName();
deviceInfo.ipAddress = info.GetIP();
deviceInfo.macAddress = info.GetMAC();
deviceInfo.deviceClass = info.GetDeviceClass();
// 获取图像尺寸
GetWidth(deviceInfo.width);
GetHeight(deviceInfo.height);
return SUCCESS;
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_NO_OPEN);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_bDeviceOpen || !m_hDevice) {
return ERR_CODE(DEV_NO_OPEN);
}
// 从缓存的设备信息中获取(在 EnumerateDevices 时已获取)
deviceInfo = m_deviceInfo;
// 获取图像尺寸
GetWidth(deviceInfo.width);
GetHeight(deviceInfo.height);
return SUCCESS;
#endif
}
// 设置触发模式
int CGalaxyDevice::SetTriggerMode(bool enable)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
CEnumFeaturePointer ptrTriggerMode = m_objFeatureControlPtr->GetEnumFeature("TriggerMode");
if (!ptrTriggerMode.IsNull()) {
ptrTriggerMode->SetValue(enable ? "On" : "Off");
}
return SUCCESS;
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
GX_STATUS status = GXSetEnum(m_hDevice, GX_ENUM_TRIGGER_MODE,
enable ? GX_TRIGGER_MODE_ON : GX_TRIGGER_MODE_OFF);
return (status == GX_STATUS_SUCCESS) ? SUCCESS : static_cast<int>(status);
#endif
}
// 发送软触发
int CGalaxyDevice::SendSoftTrigger()
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
CCommandFeaturePointer ptrTriggerSoftware = m_objFeatureControlPtr->GetCommandFeature("TriggerSoftware");
if (!ptrTriggerSoftware.IsNull()) {
ptrTriggerSoftware->Execute();
}
return SUCCESS;
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
GX_STATUS status = GXSendCommand(m_hDevice, GX_COMMAND_TRIGGER_SOFTWARE);
return (status == GX_STATUS_SUCCESS) ? SUCCESS : static_cast<int>(status);
#endif
}
// 开始采集
int CGalaxyDevice::StartAcquisition()
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objStreamPtr.IsNull() || m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
if (m_bAcquisitioning) {
return SUCCESS;
}
// 开始取流
m_objStreamPtr->StartGrab();
// 发送开始采集命令
CCommandFeaturePointer ptrAcquisitionStart = m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart");
if (!ptrAcquisitionStart.IsNull()) {
ptrAcquisitionStart->Execute();
}
m_bAcquisitioning = true;
return SUCCESS;
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
if (m_bAcquisitioning) {
return SUCCESS;
}
2025-12-20 16:18:12 +08:00
// 1. 先调用 GXStreamOn 开始采集
2025-12-10 00:01:32 +08:00
GX_STATUS status = GXStreamOn(m_hDevice);
2025-12-20 16:18:12 +08:00
if (status != GX_STATUS_SUCCESS) {
LOG_DEBUG("GXStreamOn failed: %d\n", status);
return static_cast<int>(status);
2025-12-10 00:01:32 +08:00
}
2025-12-20 16:18:12 +08:00
LOG_DEBUG("GXStreamOn success\n");
m_bAcquisitioning = true;
return SUCCESS;
2025-12-10 00:01:32 +08:00
#endif
}
// 停止采集
int CGalaxyDevice::StopAcquisition()
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (!m_bAcquisitioning) {
return SUCCESS;
}
// 发送停止采集命令
if (!m_objFeatureControlPtr.IsNull()) {
CCommandFeaturePointer ptrAcquisitionStop = m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop");
if (!ptrAcquisitionStop.IsNull()) {
ptrAcquisitionStop->Execute();
}
}
// 停止取流
if (!m_objStreamPtr.IsNull()) {
m_objStreamPtr->StopGrab();
}
// 注销回调
if (m_pCaptureEventHandler && !m_objStreamPtr.IsNull()) {
m_objStreamPtr->UnregisterCaptureCallback();
delete m_pCaptureEventHandler;
m_pCaptureEventHandler = nullptr;
}
m_bAcquisitioning = false;
return SUCCESS;
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_bAcquisitioning) {
return SUCCESS;
}
2025-12-20 16:18:12 +08:00
// 1. 发送停止采集命令
2025-12-10 00:01:32 +08:00
if (m_hDevice) {
2025-12-20 16:18:12 +08:00
// 2. 调用 GXStreamOff 停止采集
2025-12-10 00:01:32 +08:00
GX_STATUS status = GXStreamOff(m_hDevice);
if (status != GX_STATUS_SUCCESS) {
2025-12-20 16:18:12 +08:00
LOG_DEBUG("GXStreamOff failed: %d\n", status);
m_bAcquisitioning = false;
2025-12-10 00:01:32 +08:00
return static_cast<int>(status);
}
}
m_bAcquisitioning = false;
2025-12-20 16:18:12 +08:00
LOG_DEBUG("Acquisition stopped successfully\n");
2025-12-10 00:01:32 +08:00
return SUCCESS;
#endif
}
// 检查是否正在采集
bool CGalaxyDevice::IsAcquisitioning()
{
return m_bAcquisitioning;
}
// 单次采集图像 - 简化实现
int CGalaxyDevice::CaptureImage(GalaxyImageData& image, unsigned int timeout)
{
#ifdef _WIN32
// Windows平台使用C++ API
try {
if (m_objStreamPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
// 同步获取一帧图像
CImageDataPointer pImageData = m_objStreamPtr->GetImage(timeout);
if (pImageData.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
// 填充图像数据
image.width = static_cast<unsigned int>(pImageData->GetWidth());
image.height = static_cast<unsigned int>(pImageData->GetHeight());
image.pixelFormat = static_cast<int>(pImageData->GetPixelFormat());
image.frameID = pImageData->GetFrameID();
image.timestamp = 0;
// 计算数据大小
image.dataSize = image.width * image.height;
if (image.pixelFormat == GX_PIXEL_FORMAT_MONO8) {
image.dataSize *= 1;
} else if (image.pixelFormat == GX_PIXEL_FORMAT_RGB8) {
image.dataSize *= 3;
}
// 分配内存并复制数据
image.pData = new unsigned char[image.dataSize];
memcpy(image.pData, pImageData->GetBuffer(), image.dataSize);
return SUCCESS;
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM平台使用C API
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
GX_STATUS status;
// 获取图像 buffer 大小
int64_t nPayLoadSize = 0;
status = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &nPayLoadSize);
if (status != GX_STATUS_SUCCESS || nPayLoadSize <= 0) {
return ERR_CODE(DEV_CTRL_ERR);
}
// 分配图像缓冲区
GX_FRAME_DATA frameData;
memset(&frameData, 0, sizeof(GX_FRAME_DATA));
frameData.pImgBuf = malloc((size_t)nPayLoadSize);
if (!frameData.pImgBuf) {
return ERR_CODE(DATA_ERR_MEM);
}
status = GXSendCommand(m_hDevice, GX_COMMAND_ACQUISITION_START);
LOG_DEBUG("Command GX_COMMAND_ACQUISITION_START %d\n", status);
ERR_CODE_RETURN(status);
// 获取图像数据
while(GXGetImage(m_hDevice, &frameData, timeout) != GX_STATUS_SUCCESS)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
LOG_DEBUG("Command GXGetImage %d\n", frameData.nStatus);
// 检查帧状态
if (frameData.nStatus != GX_FRAME_STATUS_SUCCESS) {
free(frameData.pImgBuf);
return ERR_CODE(DEV_CTRL_ERR);
}else{
// 填充图像数据
image.width = frameData.nWidth;
image.height = frameData.nHeight;
image.pixelFormat = frameData.nPixelFormat;
image.frameID = frameData.nFrameID;
image.timestamp = frameData.nTimestamp;
image.dataSize = frameData.nImgSize;
// 分配内存并复制数据
image.pData = new unsigned char[image.dataSize];
memcpy(image.pData, frameData.pImgBuf, image.dataSize);
// 释放临时缓冲区
free(frameData.pImgBuf);
}
status = GXSendCommand(m_hDevice, GX_COMMAND_ACQUISITION_STOP);
return status;
#endif
2025-12-10 00:01:32 +08:00
}
// 注册图像回调
int CGalaxyDevice::RegisterImageCallback(GalaxyImageCallback callback)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objStreamPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
m_imageCallback = callback;
// 创建并注册回调处理器
if (!m_pCaptureEventHandler) {
m_pCaptureEventHandler = new CCaptureEventHandler(this);
}
m_objStreamPtr->RegisterCaptureCallback(m_pCaptureEventHandler, nullptr);
return SUCCESS;
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
2025-12-20 16:18:12 +08:00
// Linux/ARM 平台:使用 C API注册回调
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
2025-12-10 00:01:32 +08:00
m_imageCallback = callback;
2025-12-20 16:18:12 +08:00
// 注册采集回调函数
GX_STATUS status = GXRegisterCaptureCallback(m_hDevice, this, OnFrameCallbackFun);
if (status != GX_STATUS_SUCCESS) {
LOG_DEBUG("GXRegisterCaptureCallback failed: %d\n", status);
m_imageCallback = nullptr;
return static_cast<int>(status);
}
LOG_DEBUG("GXRegisterCaptureCallback success\n");
2025-12-10 00:01:32 +08:00
return SUCCESS;
#endif
}
// 取消注册图像回调
int CGalaxyDevice::UnregisterImageCallback()
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (!m_objStreamPtr.IsNull()) {
m_objStreamPtr->UnregisterCaptureCallback();
}
if (m_pCaptureEventHandler) {
delete m_pCaptureEventHandler;
m_pCaptureEventHandler = nullptr;
}
m_imageCallback = nullptr;
return SUCCESS;
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
2025-12-20 16:18:12 +08:00
// Linux/ARM 平台:使用 C API取消注册回调
if (m_hDevice) {
GX_STATUS status = GXUnregisterCaptureCallback(m_hDevice);
if (status != GX_STATUS_SUCCESS) {
LOG_DEBUG("GXUnregisterCaptureCallback failed: %d\n", status);
}
}
2025-12-10 00:01:32 +08:00
m_imageCallback = nullptr;
return SUCCESS;
#endif
}
#ifdef _WIN32
// 图像回调处理(仅 Windows 平台)
void CGalaxyDevice::ProcessCapturedImage(CImageDataPointer& objImageDataPointer)
{
if (!m_imageCallback || objImageDataPointer.IsNull()) {
return;
}
try {
GalaxyImageData imageData;
// 获取图像信息
imageData.width = static_cast<unsigned int>(objImageDataPointer->GetWidth());
imageData.height = static_cast<unsigned int>(objImageDataPointer->GetHeight());
imageData.pixelFormat = static_cast<int>(objImageDataPointer->GetPixelFormat());
imageData.frameID = objImageDataPointer->GetFrameID();
imageData.timestamp = 0; // Galaxy SDK没有直接的GetTimestamp
// 计算数据大小
imageData.dataSize = imageData.width * imageData.height;
if (imageData.pixelFormat == GX_PIXEL_FORMAT_MONO8) {
imageData.dataSize *= 1;
} else if (imageData.pixelFormat == GX_PIXEL_FORMAT_RGB8) {
imageData.dataSize *= 3;
}
// 获取图像数据指针
imageData.pData = static_cast<unsigned char*>(objImageDataPointer->GetBuffer());
// 调用用户回调
if (m_imageCallback) {
m_imageCallback(imageData);
}
}
catch (...) {
// 忽略回调中的异常
}
}
2025-12-20 16:18:12 +08:00
#else
// Linux/ARM <20><>采图线程函数
void GX_STDC CGalaxyDevice::OnFrameCallbackFun(GX_FRAME_CALLBACK_PARAM* pFrame)
{
if (pFrame == nullptr || pFrame->pUserParam == nullptr) {
return;
}
// 从用户参数中获取设备对象指针
CGalaxyDevice* pDevice = static_cast<CGalaxyDevice*>(pFrame->pUserParam);
// 检查帧状态
if (pFrame->status == GX_FRAME_STATUS_SUCCESS) {
// 如果有回调函数,调用回调
if (pDevice->m_imageCallback) {
GalaxyImageData imageData;
imageData.width = pFrame->nWidth;
imageData.height = pFrame->nHeight;
imageData.pixelFormat = pFrame->nPixelFormat;
imageData.frameID = pFrame->nFrameID;
imageData.timestamp = pFrame->nTimestamp;
imageData.dataSize = pFrame->nImgSize;
imageData.pData = reinterpret_cast<unsigned char*>(const_cast<void*>(pFrame->pImgBuf));
try {
pDevice->m_imageCallback(imageData);
}
catch (...) {
// 忽略回调中的异常
}
}
}
}
2025-12-10 00:01:32 +08:00
#endif
// 获取图像宽度
int CGalaxyDevice::GetWidth(unsigned int& width)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
CIntFeaturePointer ptrWidth = m_objFeatureControlPtr->GetIntFeature("Width");
if (!ptrWidth.IsNull()) {
width = static_cast<unsigned int>(ptrWidth->GetValue());
return SUCCESS;
}
return ERR_CODE(DEV_CTRL_ERR);
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:简化实现,返回默认值或通过其他方式获取
// 注意:如果需要实际获取宽度,需要使用 GxGetInt 等 C API
width = 0; // 默认值,或者从 m_capturedImage 中获取
if (m_capturedImage.width > 0) {
width = m_capturedImage.width;
return SUCCESS;
}
return ERR_CODE(DEV_CTRL_ERR);
#endif
}
// 获取图像高度
int CGalaxyDevice::GetHeight(unsigned int& height)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
CIntFeaturePointer ptrHeight = m_objFeatureControlPtr->GetIntFeature("Height");
if (!ptrHeight.IsNull()) {
height = static_cast<unsigned int>(ptrHeight->GetValue());
return SUCCESS;
}
return ERR_CODE(DEV_CTRL_ERR);
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:简化实现,返回默认值或通过其他方式获取
height = 0; // 默认值,或者从 m_capturedImage 中获取
if (m_capturedImage.height > 0) {
height = m_capturedImage.height;
return SUCCESS;
}
return ERR_CODE(DEV_CTRL_ERR);
#endif
}
// 设置ROI - 简化实现
int CGalaxyDevice::SetROI(const GalaxyROI& roi)
{
// 简化实现:返回成功但不做处理
return SUCCESS;
}
// 获取ROI - 简化实现
int CGalaxyDevice::GetROI(GalaxyROI& roi)
{
// 简化实现:返回默认值
roi.offsetX = 0;
roi.offsetY = 0;
roi.width = 0;
roi.height = 0;
return SUCCESS;
}
// 设置曝光时间
int CGalaxyDevice::SetExposureTime(double exposureTime)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_UNSUPPORT);
}
CFloatFeaturePointer ptrExposureTime = m_objFeatureControlPtr->GetFloatFeature("ExposureTime");
if (!ptrExposureTime.IsNull()) {
ptrExposureTime->SetValue(exposureTime);
return SUCCESS;
}
return ERR_CODE(DEV_UNSUPPORT);
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_UNSUPPORT);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
GX_STATUS status = GXSetFloat(m_hDevice, GX_FLOAT_EXPOSURE_TIME, exposureTime);
return (status == GX_STATUS_SUCCESS) ? SUCCESS : static_cast<int>(status);
#endif
}
// 获取曝光时间
int CGalaxyDevice::GetExposureTime(double& exposureTime)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
CFloatFeaturePointer ptrExposureTime = m_objFeatureControlPtr->GetFloatFeature("ExposureTime");
if (!ptrExposureTime.IsNull()) {
exposureTime = ptrExposureTime->GetValue();
return SUCCESS;
}
return ERR_CODE(DEV_CTRL_ERR);
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
GX_STATUS status = GXGetFloat(m_hDevice, GX_FLOAT_EXPOSURE_TIME, &exposureTime);
return (status == GX_STATUS_SUCCESS) ? SUCCESS : static_cast<int>(status);
#endif
}
// 设置增益
int CGalaxyDevice::SetGain(double gain)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
CFloatFeaturePointer ptrGain = m_objFeatureControlPtr->GetFloatFeature("Gain");
if (!ptrGain.IsNull()) {
ptrGain->SetValue(gain);
return SUCCESS;
}
return ERR_CODE(DEV_CTRL_ERR);
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
GX_STATUS status = GXSetFloat(m_hDevice, GX_FLOAT_GAIN, gain);
return (status == GX_STATUS_SUCCESS) ? SUCCESS : static_cast<int>(status);
#endif
}
// 获取增益
int CGalaxyDevice::GetGain(double& gain)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
CFloatFeaturePointer ptrGain = m_objFeatureControlPtr->GetFloatFeature("Gain");
if (!ptrGain.IsNull()) {
gain = ptrGain->GetValue();
return SUCCESS;
}
return ERR_CODE(DEV_CTRL_ERR);
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
GX_STATUS status = GXGetFloat(m_hDevice, GX_FLOAT_GAIN, &gain);
return (status == GX_STATUS_SUCCESS) ? SUCCESS : static_cast<int>(status);
#endif
}
// 设置帧率
int CGalaxyDevice::SetFrameRate(double frameRate)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
CFloatFeaturePointer ptrFrameRate = m_objFeatureControlPtr->GetFloatFeature("AcquisitionFrameRate");
if (!ptrFrameRate.IsNull()) {
ptrFrameRate->SetValue(frameRate);
return SUCCESS;
}
return ERR_CODE(DEV_CTRL_ERR);
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
GX_STATUS status = GXSetFloat(m_hDevice, GX_FLOAT_ACQUISITION_FRAME_RATE, frameRate);
return (status == GX_STATUS_SUCCESS) ? SUCCESS : static_cast<int>(status);
#endif
}
// 获取帧率
int CGalaxyDevice::GetFrameRate(double& frameRate)
{
#ifdef _WIN32
// Windows 平台:使用 C++ API
try {
if (m_objFeatureControlPtr.IsNull()) {
return ERR_CODE(DEV_CTRL_ERR);
}
CFloatFeaturePointer ptrFrameRate = m_objFeatureControlPtr->GetFloatFeature("AcquisitionFrameRate");
if (!ptrFrameRate.IsNull()) {
frameRate = ptrFrameRate->GetValue();
return SUCCESS;
}
return ERR_CODE(DEV_CTRL_ERR);
}
catch (CGalaxyException& e) {
return static_cast<int>(e.GetErrorCode());
}
catch (...) {
return ERR_CODE(DEV_CTRL_ERR);
}
#else
// Linux/ARM 平台:使用 C API
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
GX_STATUS status = GXGetFloat(m_hDevice, GX_FLOAT_ACQUISITION_FRAME_RATE, &frameRate);
return (status == GX_STATUS_SUCCESS) ? SUCCESS : static_cast<int>(status);
#endif
}
// 以下特性控制方法为简化实现
int CGalaxyDevice::SetIntFeature(const std::string& featureName, int64_t value)
{
return ERR_CODE(DEV_UNSUPPORT); // 简化实现
}
int CGalaxyDevice::GetIntFeature(const std::string& featureName, int64_t& value)
{
return ERR_CODE(DEV_CTRL_ERR); // 简化实现
}
int CGalaxyDevice::SetFloatFeature(const std::string& featureName, double value)
{
return ERR_CODE(DEV_UNSUPPORT); // 简化实现
}
int CGalaxyDevice::GetFloatFeature(const std::string& featureName, double& value)
{
return ERR_CODE(DEV_CTRL_ERR); // 简化实现
}
int CGalaxyDevice::SetEnumFeature(const std::string& featureName, int64_t value)
{
return ERR_CODE(DEV_UNSUPPORT); // 简化实现
}
int CGalaxyDevice::GetEnumFeature(const std::string& featureName, int64_t& value)
{
return ERR_CODE(DEV_CTRL_ERR); // 简化实现
}
int CGalaxyDevice::ExecuteCommand(const std::string& featureName)
{
return ERR_CODE(DEV_CTRL_ERR); // 简化实现
}