381 lines
12 KiB
C
381 lines
12 KiB
C
![]() |
#include "Vision.h"
|
|||
|
#include "Types.h"
|
|||
|
#include <stdio.h>
|
|||
|
#include <string.h>
|
|||
|
/*
|
|||
|
#include <sys/types.h>
|
|||
|
#include <sys/stat.h>
|
|||
|
#include <sys/ioctl.h>
|
|||
|
*/
|
|||
|
#include <fcntl.h>
|
|||
|
#include <linux/videodev2.h>
|
|||
|
|
|||
|
|
|||
|
#if defined(__GNUC__)
|
|||
|
#include <unistd.h>
|
|||
|
#endif
|
|||
|
#if defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64)
|
|||
|
#include <Windows.h>
|
|||
|
#endif
|
|||
|
#define V4L2_DEV "/dev/video0"
|
|||
|
#define WIDTH 1920
|
|||
|
#define HEIGHT 1080
|
|||
|
|
|||
|
// 初始化V4L2虚拟设备
|
|||
|
int init_v4l2(int fd) {
|
|||
|
struct v4l2_format fmt = {0};
|
|||
|
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
|
|||
|
fmt.fmt.pix.width = WIDTH;
|
|||
|
fmt.fmt.pix.height = HEIGHT;
|
|||
|
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
|
|||
|
fmt.fmt.pix.field = V4L2_FIELD_NONE;
|
|||
|
|
|||
|
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
|
|||
|
perror("Failed to set V4L2 format");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
/*
|
|||
|
bool FrameProcCb(uint16_t* pFrameInShort, uint16_t iFrameID,
|
|||
|
int32_t iFrameWidth, int32_t iFrameHeight,
|
|||
|
uint32_t iTimeCount, void* pParam) {
|
|||
|
int v4l_fd = *(int*)pParam;
|
|||
|
|
|||
|
if (pFrameInShort) {
|
|||
|
// 直接写入V4L2设备(假设数据已经是YUYV格式)
|
|||
|
if (write(v4l_fd, pFrameInShort, iFrameWidth * iFrameHeight * 2) < 0) {
|
|||
|
perror("V4L2 write failed");
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true; // 继续接收帧
|
|||
|
}
|
|||
|
return false; // 停止接收
|
|||
|
}
|
|||
|
*/
|
|||
|
bool FrameProcCb(uint16_t* pFrameInShort, uint16_t iFrameID,
|
|||
|
int32_t iFrameWidth, int32_t iFrameHeight,
|
|||
|
uint32_t iTimeCount, void* pParam) {
|
|||
|
int v4l_fd = *(int*)pParam;
|
|||
|
|
|||
|
if (pFrameInShort) {
|
|||
|
// 1. 转换12bit raw到V4L2支持的格式(以YUYV为例)
|
|||
|
size_t yuyv_size = iFrameWidth * iFrameHeight * 2; // YUYV每像素2字节
|
|||
|
unsigned char* yuyv_buffer = malloc(yuyv_size);
|
|||
|
|
|||
|
// 简易转换(实际需根据12bit raw的具体排列方式调整)
|
|||
|
for (int i = 0; i < iFrameWidth * iFrameHeight; i++) {
|
|||
|
// 取高8位作为Y分量(示例,实际转换算法需根据raw格式调整)
|
|||
|
yuyv_buffer[i*2] = (pFrameInShort[i] >> 4) & 0xFF; // Y
|
|||
|
yuyv_buffer[i*2+1] = i % 2 ? 0x80 : 0x00; // U/V交替(示例值)
|
|||
|
}
|
|||
|
|
|||
|
// 2. 写入V4L2设备
|
|||
|
if (write(v4l_fd, yuyv_buffer, yuyv_size) < 0) {
|
|||
|
perror("V4L2 write failed");
|
|||
|
free(yuyv_buffer);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
free(yuyv_buffer);
|
|||
|
return true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
int main(void)
|
|||
|
{
|
|||
|
int v4l_fd = open(V4L2_DEV, O_WRONLY);
|
|||
|
if (v4l_fd < 0 || init_v4l2(v4l_fd)) {
|
|||
|
fprintf(stderr, "Failed to initialize V4L2 device\n");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
unsigned int iDeviceNum = 0;
|
|||
|
const char* pDeviceID = NULL;
|
|||
|
SDeviceInfo sDeviceInfo;
|
|||
|
SNICInfo sLocalInfo;
|
|||
|
int64_t iValue = 0;
|
|||
|
double fValue = 0;
|
|||
|
int64_t iEntryID = 0;
|
|||
|
int32_t iWidth = 0;
|
|||
|
int32_t iHeight = 0;
|
|||
|
int32_t iPixelBits = 0;
|
|||
|
int32_t iPixelIndex = 0;
|
|||
|
uint16_t iFrameID = 0;
|
|||
|
uint32_t iTimeCount = 0;
|
|||
|
unsigned int i = 0;
|
|||
|
int j = 0;
|
|||
|
int k = 0;
|
|||
|
int iAttributeNumber = -1;
|
|||
|
EAttrType eAttrType;
|
|||
|
EAttrAccessMode eAccessMode;
|
|||
|
char* pValue = NULL;
|
|||
|
int iEntryNumber = -1;
|
|||
|
char* pFrame = NULL;
|
|||
|
uint16_t* pFrameInShort = NULL;
|
|||
|
char* pMappedFrame = NULL;
|
|||
|
FILE* pFile = NULL;
|
|||
|
int32_t iPixelNum = 0;
|
|||
|
Stream pStream = NULL;
|
|||
|
int iKey = 0;
|
|||
|
//Init
|
|||
|
Init();
|
|||
|
//GetVersion
|
|||
|
fprintf(stderr, "SDK Version: %s\n", GetVersionText());
|
|||
|
//SetCallLogEnable
|
|||
|
if(SetCallLogEnable(true))
|
|||
|
{
|
|||
|
fprintf(stderr, "SetCallLogEnable=Enable\n");
|
|||
|
}else{
|
|||
|
fprintf(stderr, "SetCallLogEnable=Error:%s\n", GetLastErrorText());
|
|||
|
return 0;
|
|||
|
}
|
|||
|
//SearchforDevice
|
|||
|
iDeviceNum = SearchforDevice();
|
|||
|
if(iDeviceNum >= 0){
|
|||
|
fprintf(stderr, "\nTotal number of devices: %d\n\n", iDeviceNum);
|
|||
|
}else{
|
|||
|
//Uninit
|
|||
|
Uninit();
|
|||
|
fprintf(stderr, "Press Enter key to exit\n");
|
|||
|
scanf("%c", &iKey);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
for(i = 0; i < iDeviceNum; i++){
|
|||
|
//Get device MAC
|
|||
|
pDeviceID = GetDeviceID(i);
|
|||
|
fprintf(stderr, "***************************************************************\n");
|
|||
|
fprintf(stderr, " Device Information:\n");
|
|||
|
|
|||
|
//GetDeviceInfo
|
|||
|
GetDeviceInfo(pDeviceID, &sDeviceInfo);
|
|||
|
fprintf(stderr, " MAC=%s\n", sDeviceInfo.pMac);
|
|||
|
fprintf(stderr, " IP=%s\n", sDeviceInfo.pIP);
|
|||
|
fprintf(stderr, " Control Port=%d\n", sDeviceInfo.iCtrlPort);
|
|||
|
fprintf(stderr, " Data Port=%d\n", sDeviceInfo.iDataPort);
|
|||
|
fprintf(stderr, " Mask=%s\n", sDeviceInfo.pMask);
|
|||
|
fprintf(stderr, " Gateway=%s\n", sDeviceInfo.pGateway);
|
|||
|
fprintf(stderr, " VenderName=%s\n", sDeviceInfo.pVenderName);
|
|||
|
fprintf(stderr, " ModelName=%s\n", sDeviceInfo.pModelName);
|
|||
|
fprintf(stderr, " Version=%s\n", sDeviceInfo.pVersion);
|
|||
|
fprintf(stderr, " SerialNumber=%s\n", sDeviceInfo.pSerialNumber);
|
|||
|
if(sDeviceInfo.bReachable){
|
|||
|
fprintf(stderr, " Reachable\n");
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Unreachable\n");
|
|||
|
}
|
|||
|
|
|||
|
//LocalInfo
|
|||
|
GetLocalNICInfo(pDeviceID,&sLocalInfo);
|
|||
|
fprintf(stderr, " Localf Network Adapter Information:\n");
|
|||
|
fprintf(stderr, " MAC=%s\n", sLocalInfo.pMac);
|
|||
|
fprintf(stderr, " IP=%s\n", sLocalInfo.pIP);
|
|||
|
fprintf(stderr, " Mask=%s\n", sLocalInfo.pMask);
|
|||
|
fprintf(stderr, " InterfaceName=%s\n", sLocalInfo.pInterfaceName);
|
|||
|
fprintf(stderr, " Broadcast=%s\n", sLocalInfo.pBroadcast);
|
|||
|
|
|||
|
//Force IP
|
|||
|
if(ForceIP(pDeviceID, sDeviceInfo.pIP, sLocalInfo.pMask, sDeviceInfo.pGateway)){
|
|||
|
fprintf(stderr, " ForceIP=OK\n");
|
|||
|
}else{
|
|||
|
fprintf(stderr, " ForceIP=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
//OpenDevice
|
|||
|
if(OpenDevice(pDeviceID)){
|
|||
|
fprintf(stderr, " OpenDevice=OK\n");
|
|||
|
}else{
|
|||
|
fprintf(stderr, " OpenDevice=Error:%s\n", GetLastErrorText());
|
|||
|
continue;
|
|||
|
}
|
|||
|
//The following code is to demonstrate how to set or get related parameters of each attribute
|
|||
|
//Get the number of attributes
|
|||
|
iAttributeNumber = GetNumberOfAttribute(pDeviceID);
|
|||
|
if(iAttributeNumber >= 0){
|
|||
|
fprintf(stderr, " Attribute information, %d in total:\n", iAttributeNumber);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " GetNumberOfAttribute=Error:%s\n", GetLastErrorText());
|
|||
|
continue;
|
|||
|
}
|
|||
|
for(j = 0; j < iAttributeNumber; j++){
|
|||
|
//GetAttributeName, GetAttributeType, GetAttribute, SetAttribute
|
|||
|
const char* pAttrName = GetAttributeName(pDeviceID, j);
|
|||
|
if(pAttrName == NULL){
|
|||
|
fprintf(stderr, " GetAttributeName=Error:%s\n", GetLastErrorText());
|
|||
|
continue;
|
|||
|
}
|
|||
|
fprintf(stderr, "++++Name=%s\n", pAttrName);
|
|||
|
if(!GetAttributeType(pDeviceID, pAttrName, &eAttrType)){
|
|||
|
fprintf(stderr, " GetAttributeType=Error:%s\n", GetLastErrorText());
|
|||
|
continue;
|
|||
|
}
|
|||
|
if(eAttrType == INT_T){
|
|||
|
fprintf(stderr, " Value Type=int\n");
|
|||
|
iValue = 0;
|
|||
|
if(GetAttrMaxInt(pDeviceID, pAttrName, &iValue)){
|
|||
|
fprintf(stderr, " Maximum=%d\n", iValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Maximum=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
if(GetAttrMinInt(pDeviceID, pAttrName, &iValue)){
|
|||
|
fprintf(stderr, " Minimum=%d\n", iValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Minimum=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
if(GetAttrIncInt(pDeviceID, pAttrName, &iValue)){
|
|||
|
fprintf(stderr, " Increment=%d\n", iValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Increment=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
if(GetAttrInt(pDeviceID, pAttrName, &iValue, DDR_T)){
|
|||
|
fprintf(stderr, " Current Value=%d\n", iValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Current Value=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
if(SetAttrInt(pDeviceID, pAttrName, iValue, DDR_T)){
|
|||
|
fprintf(stderr, " New Value=%d\n", iValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " New Value=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
}else if(eAttrType == DOUBLE_T){
|
|||
|
fprintf(stderr, " Value Type=double\n");
|
|||
|
fValue = 0;
|
|||
|
if(GetAttrMaxFloat(pDeviceID, pAttrName, &fValue)){
|
|||
|
fprintf(stderr, " Maximum=%f\n", fValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Maximum=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
if(GetAttrMinFloat(pDeviceID, pAttrName, &fValue)){
|
|||
|
fprintf(stderr, " Minimum=%f\n", fValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Minimum=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
if(GetAttrIncFloat(pDeviceID, pAttrName, &fValue)){
|
|||
|
fprintf(stderr, " Increment=%f\n", fValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Increment=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
if(GetAttrFloat(pDeviceID, pAttrName, &fValue, DDR_T)){
|
|||
|
fprintf(stderr, " Current Value=%f\n", fValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Current Value=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
if(SetAttrFloat(pDeviceID, pAttrName, fValue, DDR_T)){
|
|||
|
fprintf(stderr, " New Value=%f\n", fValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " New Value=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
}else if(eAttrType == STRING_T){
|
|||
|
fprintf(stderr, " Value Type=string\n");
|
|||
|
pValue = (char*)malloc(ATTR_TXT_SIZE_IN_BYTES);
|
|||
|
if(GetAttrString(pDeviceID, pAttrName, pValue, DDR_T)){
|
|||
|
fprintf(stderr, " Current Value=%s\n", pValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Current Value=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
free(pValue);
|
|||
|
}else if(eAttrType == ENUMERATION_T){
|
|||
|
fprintf(stderr, " Value Type=enumeration\n");
|
|||
|
fprintf(stderr, " Enumeration Entries:\n");
|
|||
|
//Get number of entries
|
|||
|
iEntryNumber = GetNumberOfEntry(pDeviceID, pAttrName);
|
|||
|
//Display entries
|
|||
|
for(k = 0; k < iEntryNumber; k++){
|
|||
|
int iEntryID = GetEntryID(pDeviceID, pAttrName, k);
|
|||
|
const char* pEntryName = GetEntryName(pDeviceID, pAttrName, k);
|
|||
|
if(iEntryID != -1 && pEntryName != NULL){
|
|||
|
fprintf(stderr, " %d=%s\n", iEntryID, pEntryName);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Fail to get the entry with index=%d\n", k);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
iEntryID = 0;
|
|||
|
if(GetAttrInt(pDeviceID, pAttrName, &iEntryID, DDR_T)){
|
|||
|
fprintf(stderr, " Current Value=%lld text=%s\n", iEntryID, GetEntryNameByID(pDeviceID, pAttrName, (unsigned int)iEntryID));
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Current Value=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
if(SetAttrInt(pDeviceID, pAttrName, iEntryID, DDR_T)){
|
|||
|
fprintf(stderr, " New Value=%d\n", iEntryID);
|
|||
|
}else{
|
|||
|
fprintf(stderr, " New Value=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Value Type=Unsupported\n");
|
|||
|
}
|
|||
|
//GetAttributeAccessMode
|
|||
|
if(GetAttributeAccessMode(pDeviceID, pAttrName, &eAccessMode)){
|
|||
|
if(eAccessMode == RO_T){
|
|||
|
fprintf(stderr, " Access Mode=RO\n");
|
|||
|
}else{
|
|||
|
fprintf(stderr, " Access Mode=RW\n");
|
|||
|
}
|
|||
|
}else{
|
|||
|
fprintf(stderr, " GetAttributeAccessMode=Error:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
}
|
|||
|
//The following code is to demonstrate how to set some most commonly used attributes. Before setting, one getting is called to get the default value.
|
|||
|
//Set OffsetX
|
|||
|
if(GetAttrInt(pDeviceID, "OffsetX", &iValue, DDR_T)){
|
|||
|
if(SetAttrInt(pDeviceID, "OffsetX", iValue, DDR_T)){
|
|||
|
fprintf(stderr, "Set OffsetX to %d\n", iValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, "Warnning: Fail to Set OffsetX, %s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
}else{
|
|||
|
fprintf(stderr, "Warnning: Fail to get OffsetX, %s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
|
|||
|
//Set ImageWidth
|
|||
|
if(GetAttrInt(pDeviceID, "ImageWidth", &iValue, DDR_T)){
|
|||
|
if(SetAttrInt(pDeviceID, "ImageWidth", iValue, DDR_T)){
|
|||
|
fprintf(stderr, "Set ImageWidth to %d\n", iValue);
|
|||
|
}else{
|
|||
|
fprintf(stderr, "Warnning: Fail to Set ImageWidth, %s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
}else{
|
|||
|
fprintf(stderr, "Warnning: Fail to get ImageWidth, %s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
//Create Stream
|
|||
|
pStream = CreateStream(pDeviceID);
|
|||
|
if(pStream != NULL){
|
|||
|
fprintf(stderr, "++++CreateStream=OK\n");
|
|||
|
}else{
|
|||
|
fprintf(stderr, "++++CreateStream=ERROR:%s\n", GetLastErrorText());
|
|||
|
continue;
|
|||
|
}
|
|||
|
SetStreamLogEnable(pStream, "StreamLog.txt");
|
|||
|
//There are two ways to process frames:
|
|||
|
//1:Use a callback function to process frame
|
|||
|
//Start Stream
|
|||
|
if(StartStream(pStream, true, FrameProcCb, &v4l_fd)){
|
|||
|
fprintf(stderr, "++++StartStream=OK\n");
|
|||
|
}else{
|
|||
|
fprintf(stderr, "++++StartStream=ERROR:%s\n", GetLastErrorText());
|
|||
|
continue;
|
|||
|
}
|
|||
|
#if defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64)
|
|||
|
Sleep(100);
|
|||
|
#else
|
|||
|
usleep(100000);
|
|||
|
#endif
|
|||
|
while(1);
|
|||
|
//StopStream
|
|||
|
StopStream(pStream);
|
|||
|
|
|||
|
fprintf(stderr, "FAIL to get one frame\n");
|
|||
|
}
|
|||
|
//Set frame processing
|
|||
|
if(SetFrameProc(pStream, ROTATE, 90)){
|
|||
|
fprintf(stderr, "++++SetFrameProc=OK\n");
|
|||
|
}else{
|
|||
|
fprintf(stderr, "++++SetFrameProc=ERROR:%s\n", GetLastErrorText());
|
|||
|
}
|
|||
|
//GetFrameInShort
|
|||
|
|
|||
|
//Set frame processing
|
|||
|
//Uninit
|
|||
|
Uninit();
|
|||
|
return 0;
|
|||
|
}
|