1234 lines
33 KiB
C++
1234 lines
33 KiB
C++
#include "GalaxyDevice.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()
|
||
{
|
||
#ifdef _WIN32
|
||
// Windows 平台:使用 C++ API
|
||
try {
|
||
if (m_bSDKInitialized) {
|
||
return SUCCESS;
|
||
}
|
||
|
||
IGXFactory::GetInstance().Init();
|
||
m_bSDKInitialized = true;
|
||
return SUCCESS;
|
||
}
|
||
catch (CGalaxyException& e) {
|
||
return static_cast<int>(e.GetErrorCode());
|
||
}
|
||
catch (...) {
|
||
return ERR_CODE(DEV_OPEN_ERR);
|
||
}
|
||
#else
|
||
// Linux/ARM 平台:使用 C API
|
||
if (m_bSDKInitialized) {
|
||
return SUCCESS;
|
||
}
|
||
|
||
GX_STATUS status = GXInitLib();
|
||
if (status == GX_STATUS_SUCCESS) {
|
||
m_bSDKInitialized = true;
|
||
return SUCCESS;
|
||
}
|
||
return static_cast<int>(status);
|
||
#endif
|
||
}
|
||
|
||
// 反初始化SDK
|
||
int CGalaxyDevice::UninitSDK()
|
||
{
|
||
#ifdef _WIN32
|
||
// Windows 平台:使用 C++ API
|
||
try {
|
||
if (m_bSDKInitialized) {
|
||
IGXFactory::GetInstance().Uninit();
|
||
m_bSDKInitialized = 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_bSDKInitialized) {
|
||
GX_STATUS status = GXCloseLib();
|
||
m_bSDKInitialized = false;
|
||
if (status != GX_STATUS_SUCCESS) {
|
||
return static_cast<int>(status);
|
||
}
|
||
}
|
||
return SUCCESS;
|
||
#endif
|
||
}
|
||
|
||
// 获取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);
|
||
}
|
||
|
||
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);
|
||
}
|
||
|
||
// 设置网络相机的流通道包长(提高采集性能)
|
||
bool bImplementPacketSize = false;
|
||
status = GXIsImplemented(m_hDevice, GX_INT_GEV_PACKETSIZE, &bImplementPacketSize);
|
||
if (status == GX_STATUS_SUCCESS && bImplementPacketSize) {
|
||
// int64_t nPacketSize = 0;
|
||
// status = GXGetOptimalPacketSize(m_hDevice, &nPacketSize);
|
||
// if (status == GX_STATUS_SUCCESS) {
|
||
// GXSetInt(m_hDevice, GX_INT_GEV_PACKETSIZE, nPacketSize);
|
||
// }
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
// 发送开始采集命令
|
||
GX_STATUS status = GXStreamOn(m_hDevice);
|
||
if (status == GX_STATUS_SUCCESS) {
|
||
m_bAcquisitioning = true;
|
||
return SUCCESS;
|
||
}
|
||
return static_cast<int>(status);
|
||
#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;
|
||
}
|
||
|
||
if (m_hDevice) {
|
||
GX_STATUS status = GXStreamOff(m_hDevice);
|
||
m_bAcquisitioning = false;
|
||
if (status != GX_STATUS_SUCCESS) {
|
||
return static_cast<int>(status);
|
||
}
|
||
}
|
||
|
||
m_bAcquisitioning = false;
|
||
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 - 简化实现,不支持回调
|
||
m_imageCallback = callback;
|
||
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 - 简化实现
|
||
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 (...) {
|
||
// 忽略回调中的异常
|
||
}
|
||
}
|
||
#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); // 简化实现
|
||
}
|