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;
|
||
}
|