diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Build/Make/Makefile new file mode 100644 index 0000000..98af8ae --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Build/Make/Makefile @@ -0,0 +1,60 @@ +PROJECT_NAME = mako2v4l + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/../.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk +include $(MAKE_INCLUDE_DIR)/VimbaImageTransform.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + -I$(OBJ_DIR) \ + -I$(VIMBASDK_DIR)/VimbaCPP/Include \ + -I$(VIMBASDK_DIR)/VimbaImageTransform/Include + +LIBS = $(VIMBACPP_LIBS) \ + $(VIMBAIMAGETRANSFORM_LIBS) \ + -lv4l2 + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) \ + $(VIMBAIMAGETRANSFORM_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ApiController.o \ + $(OBJ_DIR)/FrameObserver.o \ + $(OBJ_DIR)/main.o + +DEPENDENCIES = VimbaCPP \ + VimbaImageTransform + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/ApiController.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/ApiController.cpp new file mode 100644 index 0000000..493e1c1 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/ApiController.cpp @@ -0,0 +1,149 @@ +#include "ApiController.h" +#include "FrameObserver.h" +#include +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +ApiController::ApiController() + : m_system(VimbaSystem::GetInstance()), + m_nWidth(0), + m_nHeight(0), + m_nPixelFormat(0) +{ +} + +ApiController::~ApiController() +{ + if (m_pCamera) { + StopContinuousImageAcquisition(); + } +} + +VmbErrorType ApiController::StartUp() +{ + return m_system.Startup(); +} + +void ApiController::ShutDown() +{ + m_system.Shutdown(); +} + +VmbErrorType ApiController::StartContinuousImageAcquisition(const std::string &rStrCameraID) +{ + VmbErrorType res = m_system.OpenCameraByID(rStrCameraID.c_str(), + VmbAccessModeFull, + m_pCamera); + if (VmbErrorSuccess == res) { + FeaturePtr pFormatFeature; + res = m_pCamera->GetFeatureByName("PixelFormat", pFormatFeature); + if (VmbErrorSuccess == res) { + VmbInt64_t pixelFormat; + res = pFormatFeature->GetValue(pixelFormat); + std::cout << "Camera Pixel Format: " << pixelFormat << std::endl; + } + } + + // Optional: Adjust packet size for GigE cameras + FeaturePtr pCommandFeature; + if (VmbErrorSuccess == m_pCamera->GetFeatureByName("GVSPAdjustPacketSize", pCommandFeature)) { + pCommandFeature->RunCommand(); + } + + // Set camera parameters + res = SetValueIntMod2(m_pCamera, "Width", m_nWidth); + if (VmbErrorSuccess == res) { + res = SetValueIntMod2(m_pCamera, "Height", m_nHeight); + } + if (VmbErrorSuccess == res) { + FeaturePtr pFormatFeature; + res = m_pCamera->GetFeatureByName("PixelFormat", pFormatFeature); + if (VmbErrorSuccess == res) { + res = pFormatFeature->GetValue(m_nPixelFormat); + } + } + + // Start acquisition with FrameObserver that streams to V4L2 + if (VmbErrorSuccess == res) { + SP_SET(m_pFrameObserver, new FrameObserver(m_pCamera)); + res = m_pCamera->StartContinuousImageAcquisition(3, m_pFrameObserver); + } + + if (VmbErrorSuccess != res && m_pCamera) { + m_pCamera->Close(); + } + + return res; +} + +VmbErrorType ApiController::StopContinuousImageAcquisition() +{ + if (m_pCamera) { + m_pCamera->StopContinuousImageAcquisition(); + return m_pCamera->Close(); + } + return VmbErrorSuccess; +} + +ApiController::CameraPtrVector ApiController::GetCameraList() +{ + CameraPtrVector cameras; + m_system.GetCameras(cameras); + return cameras; +} + +// Modified to return nullptr since we're streaming directly to V4L2 +ApiController::FramePtr ApiController::GetFrame() +{ + return FramePtr(); // Not supported in this mode +} + +VmbErrorType ApiController::QueueFrame(FramePtr pFrame) +{ + if (!m_pCamera) { + return VmbErrorDeviceNotOpen; + } + return m_pCamera->QueueFrame(pFrame); +} + +// Modified to do nothing since FrameObserver handles streaming +void ApiController::ClearFrameQueue() +{ + // No operation needed as frames are directly streamed to V4L2 +} + +int ApiController::GetWidth() const { + return static_cast(m_nWidth); +} + +int ApiController::GetHeight() const { + return static_cast(m_nHeight); +} + +VmbPixelFormatType ApiController::GetPixelFormat() const { + return static_cast(m_nPixelFormat); +} + +VmbErrorType ApiController::SetValueIntMod2(const AVT::VmbAPI::CameraPtr &camera, + const std::string &featureName, + VmbInt64_t &storage) +{ + AVT::VmbAPI::FeaturePtr pFeature; + VmbInt64_t min = 0, max = 0, inc = 0; + + VmbErrorType res = camera->GetFeatureByName(featureName.c_str(), pFeature); + if (VmbErrorSuccess == res) res = pFeature->GetRange(min, max); + if (VmbErrorSuccess == res) res = pFeature->GetIncrement(inc); + if (VmbErrorSuccess == res) { + max = max - (max % inc); + if (max % 2 != 0) max -= inc; + res = pFeature->SetValue(max); + storage = max; + } + return res; +} + +}}} // namespace AVT::VmbAPI::Examples \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/ApiController.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/ApiController.h new file mode 100644 index 0000000..56ca6e5 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/ApiController.h @@ -0,0 +1,50 @@ +#ifndef APICONTROLLER_H +#define APICONTROLLER_H + +#include +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class FrameObserver; + +class ApiController +{ +public: + typedef AVT::VmbAPI::CameraPtrVector CameraPtrVector; + typedef AVT::VmbAPI::FramePtr FramePtr; + + ApiController(); + ~ApiController(); + + VmbErrorType StartUp(); + void ShutDown(); + VmbErrorType StartContinuousImageAcquisition(const std::string& cameraID); + VmbErrorType StopContinuousImageAcquisition(); + CameraPtrVector GetCameraList(); + FramePtr GetFrame(); + VmbErrorType QueueFrame(FramePtr pFrame); + void ClearFrameQueue(); + + int GetWidth() const; + int GetHeight() const; + VmbPixelFormatType GetPixelFormat() const; + +private: + AVT::VmbAPI::VimbaSystem& m_system; + AVT::VmbAPI::CameraPtr m_pCamera; + AVT::VmbAPI::IFrameObserverPtr m_pFrameObserver; + VmbInt64_t m_nPixelFormat; + VmbInt64_t m_nWidth; + VmbInt64_t m_nHeight; + + VmbErrorType SetValueIntMod2(const AVT::VmbAPI::CameraPtr &camera, + const std::string &featureName, + VmbInt64_t &storage); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/FrameObserver.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/FrameObserver.cpp new file mode 100644 index 0000000..a30e47b --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/FrameObserver.cpp @@ -0,0 +1,108 @@ +#include "FrameObserver.h" +#include +#include +#include +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +FrameObserver::FrameObserver(const CameraPtr& pCamera) + : IFrameObserver(pCamera), m_videoFd(-1) +{ + if (!SetupVideoDevice()) { + fprintf(stderr, "Failed to setup video device\n"); + } +} + +FrameObserver::~FrameObserver() +{ + CloseVideoDevice(); +} + +bool FrameObserver::SetupVideoDevice() +{ + m_videoFd = open("/dev/video61", O_RDWR); + if (m_videoFd >= 0) { + // 初始化视频格式 + memset(&m_vfmt, 0, sizeof(m_vfmt)); + m_vfmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + + // 设置默认格式(实际分辨率将在收到第一帧时更新) + m_vfmt.fmt.pix.width = 640; + m_vfmt.fmt.pix.height = 480; + m_vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + m_vfmt.fmt.pix.field = V4L2_FIELD_NONE; + + if (ioctl(m_videoFd, VIDIOC_S_FMT, &m_vfmt) < 0) { + perror("Set video format"); + close(m_videoFd); + m_videoFd = -1; + } + + return true; + } + return false; +} + +void FrameObserver::CloseVideoDevice() +{ + if (m_videoFd >= 0) { + close(m_videoFd); + m_videoFd = -1; + } +} + +void FrameObserver::FrameReceived(const FramePtr pFrame) +{ + std::lock_guard lock(m_deviceMutex); + if (m_videoFd < 0) return; + + // 获取帧信息和数据 + VmbUchar_t* pBuffer = nullptr; + VmbUint32_t nSize = 0; + VmbUint32_t width = 0, height = 0; + VmbPixelFormatType pixelFormat; + + if (pFrame->GetImage(pBuffer) != VmbErrorSuccess || + pFrame->GetImageSize(nSize) != VmbErrorSuccess || + pFrame->GetWidth(width) != VmbErrorSuccess || + pFrame->GetHeight(height) != VmbErrorSuccess || + pFrame->GetPixelFormat(pixelFormat) != VmbErrorSuccess) { + return; + } + + // 根据相机实际格式设置V4L2格式 + m_vfmt.fmt.pix.width = width; + m_vfmt.fmt.pix.height = height; + + switch (pixelFormat) { + case VmbPixelFormatMono8: + m_vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY; // 单色8位 + m_vfmt.fmt.pix.sizeimage = width * height; + break; + case VmbPixelFormatBayerRG8: + m_vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8; // Bayer格式 + m_vfmt.fmt.pix.sizeimage = width * height; + break; + default: // 默认按YUYV处理 + m_vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + m_vfmt.fmt.pix.sizeimage = width * height * 2; + } + + // 更新V4L2设备格式 + if (ioctl(m_videoFd, VIDIOC_S_FMT, &m_vfmt) < 0) { + perror("Update video format"); + return; + } + + // 写入数据 + ssize_t written = write(m_videoFd, pBuffer, nSize); + if (written != (ssize_t)nSize) { + perror("Write to video device"); + } + + m_pCamera->QueueFrame(pFrame); +} +}}} // namespace AVT::VmbAPI::Examples \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/FrameObserver.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/FrameObserver.h new file mode 100644 index 0000000..8faf2be --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/FrameObserver.h @@ -0,0 +1,33 @@ +#ifndef FRAMEOBSERVER_H +#define FRAMEOBSERVER_H + +#include +#include +#include +#include +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class FrameObserver : public IFrameObserver +{ +public: + FrameObserver(const CameraPtr& pCamera); + virtual ~FrameObserver(); + + void FrameReceived(const FramePtr pFrame) override; + +private: + bool SetupVideoDevice(); + void CloseVideoDevice(); + + int m_videoFd; + struct v4l2_format m_vfmt; + std::mutex m_deviceMutex; +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/main.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/main.cpp new file mode 100644 index 0000000..d33b1b5 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/main.cpp @@ -0,0 +1,38 @@ +#include "ApiController.h" +#include +#include + +int main(int argc, char* argv[]) +{ + AVT::VmbAPI::Examples::ApiController controller; + + if (VmbErrorSuccess != controller.StartUp()) { + std::cerr << "Failed to start Vimba system" << std::endl; + return EXIT_FAILURE; + } + + auto cameras = controller.GetCameraList(); + if (cameras.empty()) { + std::cerr << "No cameras found" << std::endl; + controller.ShutDown(); + return EXIT_FAILURE; + } + + std::string cameraId; + cameras[0]->GetID(cameraId); + std::cout << "Using camera: " << cameraId << std::endl; + + if (VmbErrorSuccess != controller.StartContinuousImageAcquisition(cameraId)) { + std::cerr << "Failed to start image acquisition" << std::endl; + controller.ShutDown(); + return EXIT_FAILURE; + } + + std::cout << "Streaming to V4L2 device. Press Enter to stop..." << std::endl; + std::cin.get(); + + controller.StopContinuousImageAcquisition(); + controller.ShutDown(); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/res/AsynchronousGrab.png b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/res/AsynchronousGrab.png new file mode 100644 index 0000000..61642b4 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/res/AsynchronousGrab.png differ diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/res/AsynchronousGrab.qrc b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/res/AsynchronousGrab.qrc new file mode 100644 index 0000000..e9cd2c6 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/res/AsynchronousGrab.qrc @@ -0,0 +1,5 @@ + + + AsynchronousGrab.png + + diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/res/AsynchronousGrab.ui b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/res/AsynchronousGrab.ui new file mode 100644 index 0000000..7d6eab2 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/VirtualCamera/Source/res/AsynchronousGrab.ui @@ -0,0 +1,111 @@ + + + AsynchronousGrabClass + + + + 0 + 0 + 1040 + 780 + + + + + 0 + 0 + + + + + 1040 + 780 + + + + + 1040 + 780 + + + + AsynchronousGrab (Qt version) + + + + :/AsynchronousGrabQt/AsynchronousGrab.png:/AsynchronousGrabQt/AsynchronousGrab.png + + + + + + 0 + 10 + 261 + 491 + + + + + + + 0 + 580 + 1041 + 191 + + + + + + + 0 + 540 + 261 + 31 + + + + Start Image Acquisition + + + + + + 270 + 10 + 771 + 561 + + + + + 0 + 0 + + + + + + + + + + 140 + 510 + 121 + 20 + + + + ColorProcessing + + + + + + + + + +