GrabBag/Device/GalaxyDevice/Src/GalaxyDevice.cpp
2025-12-20 16:18:12 +08:00

1281 lines
36 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 "GalaxyDevice.h"
#include "GalaxySDKManager.h"
#include "VrError.h"
#include "VrLog.h"
#include <cstring>
#include <iostream>
#include <thread>
#include <chrono>
// Galaxy SDK头文件
#ifdef _WIN32
// Windows 平台使用 C++ API
#define _WINSOCKAPI_ // 防止winsock.h被包含避免与winsock2.h冲突
#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"
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;
}
int ret = GalaxySDKManager::GetInstance().InitSDK();
if (ret == SUCCESS) {
m_bSDKInitialized = true;
}
return ret;
}
// 反初始化SDK
int CGalaxyDevice::UninitSDK()
{
if (m_bSDKInitialized) {
int ret = GalaxySDKManager::GetInstance().UninitSDK();
if (ret == SUCCESS) {
m_bSDKInitialized = false;
}
return ret;
}
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);
if (m_nDeviceNum == 0) {
return ERR_CODE(DEV_NOT_FIND);
}
// 分配设备信息缓存
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);
}
// 设置采集缓冲区数量为5支持多线程并行取图
CIntFeaturePointer ptrBufferNum = m_objFeatureControlPtr->GetIntFeature("StreamBufferHandlingMode");
if (!ptrBufferNum.IsNull()) {
ptrBufferNum->SetValue(5);
}
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);
}
// 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");
}
}
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;
}
// 1. 先调用 GXStreamOn 开始采集
GX_STATUS status = GXStreamOn(m_hDevice);
if (status != GX_STATUS_SUCCESS) {
LOG_DEBUG("GXStreamOn failed: %d\n", status);
return static_cast<int>(status);
}
LOG_DEBUG("GXStreamOn success\n");
m_bAcquisitioning = true;
return SUCCESS;
#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;
}
// 1. 发送停止采集命令
if (m_hDevice) {
// 2. 调用 GXStreamOff 停止采集
GX_STATUS status = GXStreamOff(m_hDevice);
if (status != GX_STATUS_SUCCESS) {
LOG_DEBUG("GXStreamOff failed: %d\n", status);
m_bAcquisitioning = false;
return static_cast<int>(status);
}
}
m_bAcquisitioning = false;
LOG_DEBUG("Acquisition stopped successfully\n");
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
}
// 注册图像回调
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
// Linux/ARM 平台:使用 C API注册回调
if (!m_hDevice) {
return ERR_CODE(DEV_CTRL_ERR);
}
m_imageCallback = callback;
// 注册采集回调函数
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");
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
// 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);
}
}
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 (...) {
// 忽略回调中的异常
}
}
#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 (...) {
// 忽略回调中的异常
}
}
}
}
#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); // 简化实现
}