static USB_DEVICE_INFO *dev_list = NULL; /* USB 枚举结果列表 */
static int dev_count = 0; /* 检测到的 USB 设备数 */
/*
* 将工作目录切到可执行文件所在目录。
* HCUsbSDK 通过 dlopen 加载同目录下的 .so 文件,必须运行在 .so 所在目录。
*/
static void setup_chdir(void)
{
char exe[PATH_MAX], *p;
ssize_t n = readlink("/proc/self/exe", exe, sizeof(exe) - 1);
if (n <= 0) return;
exe[n] = 0;
p = strrchr(exe, '/');
if (!p) return;
*p = 0;
if (access(exe, F_OK) == 0) (void)chdir(exe);
}
int camera_init(void)
{
LONG login_id; /
USB_USER_LOGIN_INFO login_info = {0}; //登录配置结构体
USB_DEVICE_REG_RES reg_result = {0}; //注册成功结构体
setup_chdir(); //设置路径
if (!USB_Init()) return -1; //usb初始化,摄像头会切换到usb模式
dev_count = USB_GetDeviceCount(); //获取连接的usb摄像头数量
if (dev_count <= 0) { USB_Cleanup(); return -1; }
printf("Devices: %d\n", dev_count);
dev_list = malloc(dev_count * sizeof(USB_DEVICE_INFO)); //为每个设备分配内存
USB_EnumDevices(dev_count, dev_list);
login_info.dwSize = sizeof(login_info); //配置登录信息
login_info.dwTimeout = 5000;
login_info.dwVID = dev_list[0].dwVID;
login_info.dwPID = dev_list[0].dwPID;
login_info.byLoginMode = 1;
memcpy(login_info.szSerialNumber, dev_list[0].szSerialNumber, sizeof(login_info.szSerialNumber));
memcpy(login_info.szUserName, "admin", 5);
memcpy(login_info.szPassword, "12345", 5);
reg_result.dwSize = sizeof(reg_result);
login_id = USB_Login(&login_info, ®_result); //登录测试
if (login_id < 0) { printf("Login fail\n"); camera_shutdown(-1, -1); return -1; }
printf("Login OK login_id=%ld\n", (long)uid);
return (int)login_id;
}
int camera_configure(LONG uid)
{
USB_COMMON_COND channel_cond = {0};
USB_CONFIG_INPUT_INFO input_info = {0};
USB_CONFIG_OUTPUT_INFO output_info = {0};
channel_cond.dwSize = sizeof(channel_cond);
channel_cond.byChannelID = USB_CHANNEL_IR;
/* ---- 配置测温流(coding type 8 = 测温+YUV) ---- */
USB_THERMAL_STREAM_PARAM thermal_param = {0};
thermal_param.dwSize = sizeof(thermal_param);
thermal_param.byVideoCodingType = 8; //模式
thermal_param.dwWidth = 4; /* 根据 YUV_MODE 选择传输帧宽 */
thermal_param.dwHeight = 5188; /* 根据 YUV_MODE 选择传输帧高 */
thermal_param.dwFrameRate = 25; //帧数
input_info.lpCondBuffer = &channel_cond;
input_info.dwCondBufferSize = sizeof(channel_cond);
input_info.lpInBuffer = &thermal_param;
input_info.dwInBufferSize = sizeof(thermal_param);
if (!USB_SetDeviceConfig(uid, USB_SET_THERMAL_STREAM_PARAM, &input_info, &output_info))
{ printf("Set thermal param fail\n"); return 0; }
/* ---- 配置视频格式为 YUY2 ---- */
USB_VIDEO_PARAM video_param = {0};
video_param.dwVideoFormat = USB_STREAM_YUY2;
video_param.dwWidth = 4;
video_param.dwHeight = 5188;
video_param.dwFramerate = 25;
memset(&input_info, 0, sizeof(input_info));
memset(&output_info, 0, sizeof(output_info));
input_info.lpCondBuffer = &channel_cond;
input_info.dwCondBufferSize = sizeof(channel_cond);
input_info.lpInBuffer = &video_param;
input_info.dwInBufferSize = sizeof(video_param);
if (!USB_SetDeviceConfig(login_id, USB_SET_VIDEO_PARAM, &input_info, &output_info))
{ printf("Set video param fail\n"); return 0; }
return 1;
}
/* 完整帧数据(协议头 + 测温区 + YUY2,按 YUV_MODE 定长) */
static uint8_t frame_data[HEADER_BYTES + TEMP_BYTES + YUV_BYTES];
static pthread_mutex_t frame_mutex = PTHREAD_MUTEX_INITIALIZER; /* 保护 frame_data/frame_ready/ */
static volatile int frame_ready = 0; /* 新帧到达标志:on_frame 置 1,camera_get_frame 消费后置 0 */
void CALLBACK on_frame(LONG handle, USB_FRAME_INFO *frame, void *user)
{
(void)handle;
(void)user;
if (!frame || !frame->pBuf) return;
if (frame->dwBufSize < YUV_OFFSET + YUV_BYTES) return;
pthread_mutex_lock(&frame_mutex);
memcpy(frame_data, frame->pBuf, YUV_OFFSET + YUV_BYTES);
frame_ready = 1;
pthread_mutex_unlock(&frame_mutex);
}
int camera_start_stream(LONG uid)
{
USB_STREAM_CALLBACK_PARAM callback_param = {0};
callback_param.dwSize = sizeof(callback_param);
callback_param.dwStreamType = USB_STREAM_YUY2;
callback_param.funcStreamCallBack = on_frame;
LONG stream_handle = USB_StartStreamCallback(uid, &callback_param);
if (stream_handle < 0) { printf("Start stream fail\n"); return -1; }
printf("Stream started\n");
return (int)stream_handle;
}
int camera_get_frame(uint8_t *buf)
{
int ready;
pthread_mutex_lock(&frame_mutex);
ready = frame_ready;
if (ready) {
memcpy(buf, frame_data + YUV_OFFSET, YUV_BYTES);
frame_ready = 0;
}
pthread_mutex_unlock(&frame_mutex);
return ready;
}
void camera_shutdown(LONG uid, int stream_handle)
{
if (stream_handle >= 0) USB_StopChannel(uid, (DWORD)stream_handle);
if (uid >= 0) USB_Logout(uid);
free(dev_list);
dev_list = NULL;
USB_Cleanup();
}