|
|
#include <stdio.h>
|
|
|
#include <string.h>
|
|
|
#include <stdlib.h>
|
|
|
#include <pthread.h>
|
|
|
#include <unistd.h>
|
|
|
|
|
|
#include "JZsdkLib.h"
|
|
|
#include "version_choose.h"
|
|
|
#include "BaseConfig.h"
|
|
|
|
|
|
|
|
|
#include "JZsdk_usb_bulk/JZsdk_usb_bulk.h"
|
|
|
#include "../V4L2_camera/V4L2_Record.h"
|
|
|
#include "../../MultProc/MultProc.h"
|
|
|
#include "../../MediaParm.h"
|
|
|
#include "../../VideoMgmt/VideoMgmt.h"
|
|
|
#include "Ircut/ircut.h"
|
|
|
#include "../Camera.h"
|
|
|
|
|
|
#include "UI_control/UI_control.h"
|
|
|
#include "../../IRC_funtion/IRC_Param.h"
|
|
|
#include "../../IRC_funtion/IRC_funtion.h"
|
|
|
|
|
|
#define IRC_WIDTH FIRST_WIDTH
|
|
|
#define IRC_HEIGHT FIRST_HEIGHT
|
|
|
|
|
|
#define CAMERA_WIDTH SECOND_WIDTH
|
|
|
#define CAMERA_HEIGHT SECOND_HEIGHT
|
|
|
|
|
|
static int Kt_Camera_fd;
|
|
|
|
|
|
extern IRC_param *g_IRC_Param;
|
|
|
|
|
|
|
|
|
#define IRC_WIDTH FIRST_WIDTH
|
|
|
#define IRC_HEIGHT FIRST_HEIGHT
|
|
|
|
|
|
// 定义帧头长度和帧头内容
|
|
|
#define FRAME_HEADER_SIZE 4
|
|
|
|
|
|
static const unsigned char FRAME_HEADER[FRAME_HEADER_SIZE] = {0xaa, 0xbb, 0xcc, 0xdd};
|
|
|
|
|
|
|
|
|
static void *Irc_usb_index = NULL;
|
|
|
|
|
|
//红外数据纠正函数, 暂定全部替换
|
|
|
T_JZsdkReturnCode Kt_Irc_DataCorrect(unsigned char *data)
|
|
|
{
|
|
|
//像素修正
|
|
|
data[0] = data[5];
|
|
|
data[1] = data[6];
|
|
|
data[2] = data[5];
|
|
|
data[3] = data[6];
|
|
|
}
|
|
|
|
|
|
|
|
|
//红外数据接收线程
|
|
|
static void *JZsdk_Kt_Irc_DataRecv_Thread(void *args)
|
|
|
{
|
|
|
int frame_len = IRC_WIDTH*2*IRC_HEIGHT; //163840
|
|
|
unsigned char buf[163840]; //usb数据缓冲区需要为512的倍数 4194304 后续考虑为 262144
|
|
|
unsigned char frameData[frame_len]; // 存储整帧数据的画面缓冲区
|
|
|
unsigned int lineNum = 0;
|
|
|
int frame = 0;
|
|
|
int frameDataLen = 0;//缓冲区的数据长度
|
|
|
|
|
|
/*****
|
|
|
*
|
|
|
* 数据格式说明
|
|
|
*
|
|
|
* 帧头 0xaa 0xbb 0x02 0x80 0x01 0x00 + 行数 如第一行0x00 0x01
|
|
|
* 数据包长度为 0x0280
|
|
|
* 数据包 一包的行数为256 0x0100
|
|
|
* 当前数据为第x行 x= 0x0001
|
|
|
* 两位数据为一个点
|
|
|
* 接着把前4个点的数据 用第五个点替换掉
|
|
|
* *****/
|
|
|
|
|
|
while (1)
|
|
|
{
|
|
|
int realLen;
|
|
|
memset(buf,0,sizeof(buf));
|
|
|
T_JZsdkReturnCode ret = JZsdk_HalUsbBulk_ReadData(&Irc_usb_index, buf, sizeof(buf), &realLen);
|
|
|
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
|
|
|
{
|
|
|
// 处理读取错误
|
|
|
JZSDK_LOG_ERROR("读取错误");
|
|
|
continue;
|
|
|
//return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
if (realLen != 0)
|
|
|
{
|
|
|
//JZSDK_LOG_INFO("读取到%d 字节",realLen);
|
|
|
}
|
|
|
|
|
|
//寻找数据是否存在帧头
|
|
|
for (int i = 0; i < realLen; i++)
|
|
|
{
|
|
|
// 验证帧头
|
|
|
if (memcmp(buf+i, FRAME_HEADER, FRAME_HEADER_SIZE) != 0)
|
|
|
{
|
|
|
// 帧头不匹配,可能是噪声或错误的数据包
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
/**********************
|
|
|
*
|
|
|
* 方法一,将usb缓冲区调整大小 到超过640*256, 然后直接输出整段画面,避免重复复制,节省处理时间
|
|
|
*
|
|
|
* ******************************/
|
|
|
//如果查找到帧头
|
|
|
|
|
|
//查看是否是第0帧
|
|
|
if (frame == 0)
|
|
|
{
|
|
|
//重置掉画面缓冲区
|
|
|
memset(frameData,0,sizeof(frameData));
|
|
|
|
|
|
//将数据置于缓冲区
|
|
|
frameDataLen = (realLen-i);
|
|
|
memcpy( &frameData[0], buf + i, frameDataLen);
|
|
|
|
|
|
//让画面帧强跳到第一帧
|
|
|
frame = 1;
|
|
|
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
//如果是第一帧
|
|
|
if (frame == 1)
|
|
|
{
|
|
|
memcpy( &frameData[frameDataLen], buf, frame_len-frameDataLen );
|
|
|
|
|
|
VideoMgmt_write_data(&VideoMgmt_FirstRaw_index, frameData, frame_len);
|
|
|
|
|
|
frame = 2;
|
|
|
frameDataLen = 0;
|
|
|
//memset(frameData,0,sizeof(frameData));
|
|
|
}
|
|
|
|
|
|
|
|
|
//如果不是第1帧,且上段数据小于一画面段,说明为数据被切割
|
|
|
if ( i<frame_len)
|
|
|
{
|
|
|
//则于前端残余数据拼接,并输出
|
|
|
if (frame%2==0 && (frame != 1) )
|
|
|
{
|
|
|
|
|
|
memcpy( &frameData[frame_len-i], buf, i);
|
|
|
//将未处理raw数据放入缓冲区
|
|
|
|
|
|
//JZSDK_LOG_INFO("写入1 %d %x", i, frameData[20]);
|
|
|
|
|
|
VideoMgmt_write_data(&VideoMgmt_FirstRaw_index, frameData, frame_len);
|
|
|
//JZSDK_LOG_INFO("放入数据到缓冲区");
|
|
|
//memset(frameData,0,sizeof(frameData));
|
|
|
}
|
|
|
frame++;
|
|
|
}
|
|
|
|
|
|
//如果剩余长度超出一画数据,将画面数据整段输出
|
|
|
if ( (i + frame_len) < realLen)
|
|
|
{
|
|
|
if (frame%2==0)
|
|
|
{
|
|
|
//JZSDK_LOG_INFO("写入2");
|
|
|
|
|
|
memcpy( &frameData[0], buf, frame_len);
|
|
|
|
|
|
//将未处理raw数据放入缓冲区
|
|
|
VideoMgmt_write_data(&VideoMgmt_FirstRaw_index, frameData, frame_len);
|
|
|
//JZSDK_LOG_INFO("放入数据到缓冲区");
|
|
|
}
|
|
|
frame++;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
//JZSDK_LOG_INFO("i:%d, frame_len:%d realLen:%d frame:%d",i,frame_len,realLen,frame);
|
|
|
|
|
|
//如果剩余数据小于一画,存进画面缓冲区
|
|
|
//memset(frameData,0,sizeof(frameData));
|
|
|
memcpy(frameData, buf+i, (realLen-i));
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//红外相机数据的初始化
|
|
|
T_JZsdkReturnCode JZsdk_Kt_Irc_Data_Init()
|
|
|
{
|
|
|
T_JZsdkReturnCode ret;
|
|
|
|
|
|
//初始化接收的usb口
|
|
|
ret = JZsdk_HalUsbBulk_Init(&Irc_usb_index, 0, 0, LINUX_USB_PID, LINUX_USB_VID, USB_IN_POINT, USB_OUT_POINT);
|
|
|
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
|
|
|
{
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
//初始化usb接收线程
|
|
|
pthread_t ReadDataTask;
|
|
|
pthread_attr_t task_attribute; //线程属性
|
|
|
pthread_attr_init(&task_attribute); //初始化线程属性
|
|
|
pthread_attr_setdetachstate(&task_attribute, PTHREAD_CREATE_DETACHED); //设置线程分离属性
|
|
|
int opus_Protection = pthread_create(&ReadDataTask,&task_attribute,JZsdk_Kt_Irc_DataRecv_Thread,NULL); //线程
|
|
|
if(opus_Protection != 0)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("创建视频usb线程失败!");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
|
|
}
|
|
|
|
|
|
|
|
|
//红外数据的处理
|
|
|
static void *JZsdk_Kt_Irc_DataDeal_Thread(void *args)
|
|
|
{
|
|
|
int DealFrameNum = 0;
|
|
|
unsigned char BaseBuffer[IRC_WIDTH*2*IRC_HEIGHT];
|
|
|
|
|
|
while (1)
|
|
|
{
|
|
|
unsigned char *gary_data = NULL;
|
|
|
unsigned int gary_data_len;
|
|
|
//1、从原始流缓冲区中取出raw数据
|
|
|
VideoMgmt_read_data(&VideoMgmt_FirstRaw_index, &gary_data, &gary_data_len,JZ_FLAGCODE_OFF ,JZ_FLAGCODE_OFF);
|
|
|
|
|
|
//2、红外数据纠正处理
|
|
|
Kt_Irc_DataCorrect(gary_data);
|
|
|
|
|
|
//3、将灰度图数据转换为原始码流数据
|
|
|
unsigned char *raw_data = NULL;
|
|
|
int raw_data_len = 0;
|
|
|
IRC_FrameDeal(gary_data, gary_data_len, &raw_data, &raw_data_len);
|
|
|
|
|
|
//4、将原始码流数据转换成h264流,为避免多次复制,这里的h264会直接放入视频流管理的缓冲区
|
|
|
JZsdk_RTKMMP_RawData_to_h264(raw_data, raw_data_len);
|
|
|
|
|
|
//5、释放内存
|
|
|
if (raw_data != NULL)
|
|
|
{
|
|
|
if (raw_data != NULL)
|
|
|
{
|
|
|
free(raw_data);
|
|
|
raw_data = NULL;
|
|
|
}
|
|
|
|
|
|
if (gary_data != NULL)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
if (gary_data != NULL)
|
|
|
{
|
|
|
free(gary_data);
|
|
|
gary_data = NULL;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//JZSDK_LOG_DEBUG("得到了一帧红外h264");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//红外相机数据的处理线程
|
|
|
static T_JZsdkReturnCode JZsdk_Kt_Irc_DataDeal_Init()
|
|
|
{
|
|
|
pthread_t ReadDataTask;
|
|
|
pthread_attr_t task_attribute; //线程属性
|
|
|
pthread_attr_init(&task_attribute); //初始化线程属性
|
|
|
pthread_attr_setdetachstate(&task_attribute, PTHREAD_CREATE_DETACHED); //设置线程分离属性
|
|
|
int opus_Protection = pthread_create(&ReadDataTask,&task_attribute,JZsdk_Kt_Irc_DataDeal_Thread,NULL); //线程
|
|
|
if(opus_Protection != 0)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("创建红外相机数据的处理线程失败!");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
|
|
}
|
|
|
|
|
|
//光学相机数据的处理线程
|
|
|
static void *JZsdk_Kt_Cam_DataDeal_Thread(void *args)
|
|
|
{
|
|
|
int DealFrameNum = 0;
|
|
|
while (1)
|
|
|
{
|
|
|
unsigned char *raw_data = NULL;
|
|
|
unsigned int raw_data_len;
|
|
|
//1、从原始流缓冲区中取出raw数据
|
|
|
VideoMgmt_read_data(&VideoMgmt_SecondRaw_index, &raw_data, &raw_data_len,JZ_FLAGCODE_OFF ,JZ_FLAGCODE_OFF);
|
|
|
|
|
|
//2、将raw数据流转换成h264流,并放置到视频流缓冲区
|
|
|
JZsdk_Kt_CamMMP_Mjpeg_to_h264(raw_data, raw_data_len);
|
|
|
|
|
|
free(raw_data);
|
|
|
raw_data = NULL;
|
|
|
|
|
|
//DealFrameNum++;
|
|
|
//printf("get Cam Frame%d\n",DealFrameNum);
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//光学相机数据的处理线程
|
|
|
static T_JZsdkReturnCode JZsdk_Kt_Cam_DataDeal_Init()
|
|
|
{
|
|
|
pthread_t ReadDataTask;
|
|
|
pthread_attr_t task_attribute; //线程属性
|
|
|
pthread_attr_init(&task_attribute); //初始化线程属性
|
|
|
pthread_attr_setdetachstate(&task_attribute, PTHREAD_CREATE_DETACHED); //设置线程分离属性
|
|
|
int opus_Protection = pthread_create(&ReadDataTask,&task_attribute,JZsdk_Kt_Cam_DataDeal_Thread,NULL); //线程
|
|
|
if(opus_Protection != 0)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("创建红外相机数据的处理线程失败!");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
|
|
}
|
|
|
|
|
|
//光学相机数据读取线程
|
|
|
static void *JZsdk_Kt_Cam_Data_Thread(void *args)
|
|
|
{
|
|
|
while (1)
|
|
|
{
|
|
|
unsigned int buf_size = 0;
|
|
|
unsigned char *buf = NULL;
|
|
|
|
|
|
//从相机中读取一张照片
|
|
|
V4L2_CameraFrameRecord_OnlyGetFrame(&buf, &buf_size);
|
|
|
|
|
|
if (buf == NULL)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("相机数据读取失败");
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
|
|
|
//放入缓冲池
|
|
|
VideoMgmt_write_data(&VideoMgmt_SecondRaw_index, buf, buf_size);
|
|
|
|
|
|
//归还图片
|
|
|
V4L2_CameraFrameRecord_OnlyReturnFrame();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//光学相机初始化
|
|
|
static T_JZsdkReturnCode JZsdk_Kt_Camera_Init()
|
|
|
{
|
|
|
T_JZsdkReturnCode ret;
|
|
|
|
|
|
//初始化摄像头
|
|
|
ret = V4l2_Camarainit2(&Kt_Camera_fd,CAMERA_WIDTH,CAMERA_HEIGHT,30);
|
|
|
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
|
|
|
{
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
|
|
|
//初始化数据接收线程
|
|
|
pthread_t ReadDataTask;
|
|
|
pthread_attr_t task_attribute; //线程属性
|
|
|
pthread_attr_init(&task_attribute); //初始化线程属性
|
|
|
pthread_attr_setdetachstate(&task_attribute, PTHREAD_CREATE_DETACHED); //设置线程分离属性
|
|
|
int opus_Protection = pthread_create(&ReadDataTask,&task_attribute,JZsdk_Kt_Cam_Data_Thread,NULL); //线程
|
|
|
if(opus_Protection != 0)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("创建v4l2线程失败!");
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
|
|
}
|
|
|
|
|
|
//昆腾相机初始化
|
|
|
T_JZsdkReturnCode JZsdk_Kt_Irc_Camera_Init()
|
|
|
{
|
|
|
T_JZsdkReturnCode ret;
|
|
|
|
|
|
//1、初始化光学相机
|
|
|
ret = JZsdk_Kt_Camera_Init();
|
|
|
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("光学相机初始化失败");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//初始化数据转换模块
|
|
|
JZsdk_Kt_Cam_DataDeal_Init();
|
|
|
}
|
|
|
|
|
|
//2、初始化红外的数据处理
|
|
|
ret = IRC_ParamInit(&g_IRC_Param, IRC_HEIGHT, IRC_WIDTH, 25);
|
|
|
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("初始化红外的数据处理失败");
|
|
|
}
|
|
|
|
|
|
//3、初始化红外的数据输入
|
|
|
ret = JZsdk_Kt_Irc_Data_Init();
|
|
|
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
|
|
|
{
|
|
|
JZSDK_LOG_ERROR("红外相机初始化失败");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//初始化数据转换模块
|
|
|
JZsdk_Kt_Irc_DataDeal_Init();
|
|
|
}
|
|
|
|
|
|
JZSDK_LOG_INFO("KT_Irc init complete");
|
|
|
|
|
|
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
|
|
}
|
|
|
|
|
|
//昆腾的红外相机的快门开关
|
|
|
/***********************************
|
|
|
*
|
|
|
* value on为开 off为关
|
|
|
*
|
|
|
*
|
|
|
* ***************************************/
|
|
|
T_JZsdkReturnCode JZsdk_Kt_Irc_ShutterSwitch(int value)
|
|
|
{
|
|
|
T_JZsdkReturnCode ret;
|
|
|
if (value == JZ_FLAGCODE_ON)
|
|
|
{
|
|
|
ret = SysfsGPIO_Set_ircut(KT_IRC_SHUTTER_GPIO_NUM, 1);
|
|
|
}
|
|
|
else if (value == JZ_FLAGCODE_OFF)
|
|
|
{
|
|
|
ret = SysfsGPIO_Set_ircut(KT_IRC_SHUTTER_GPIO_NUM, 0);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
ret = JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|