|
@@ -0,0 +1,103 @@
|
|
|
+#include "camera.h"
|
|
|
+#include <opencv2/opencv.hpp>
|
|
|
+#include <fcntl.h>
|
|
|
+#include <sys/mman.h>
|
|
|
+#include <sys/stat.h>
|
|
|
+#include <semaphore.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <cstring>
|
|
|
+#include <iostream>
|
|
|
+#include <string>
|
|
|
+
|
|
|
+const size_t SHM_SIZE = 640 * 480 * 3; // 假设图像为640x480,RGB格式
|
|
|
+
|
|
|
+namespace Camera_shm {
|
|
|
+
|
|
|
+Camera::Camera(int id, int width, int height, int fps)
|
|
|
+ : camera_id(id), shm_name("/camera_data_" + std::to_string(id)),
|
|
|
+ sem_name("/camera_semaphore_" + std::to_string(id)), shm_fd(-1),
|
|
|
+ shm_ptr(nullptr), sem(nullptr) {
|
|
|
+ // 打开相机
|
|
|
+ cap.open(camera_id);
|
|
|
+ cap.set(cv::CAP_PROP_FRAME_WIDTH, width);
|
|
|
+ cap.set(cv::CAP_PROP_FRAME_HEIGHT, height);
|
|
|
+ cap.set(cv::CAP_PROP_FPS, fps);
|
|
|
+ cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
|
|
|
+ if (!cap.isOpened()) {
|
|
|
+ throw std::runtime_error("Failed to open camera " +
|
|
|
+ std::to_string(camera_id));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建共享内存
|
|
|
+ shm_fd = shm_open(shm_name.c_str(), O_CREAT | O_RDWR, 0666);
|
|
|
+ if (shm_fd == -1) {
|
|
|
+ throw std::runtime_error("Failed to create shared memory for camera " +
|
|
|
+ std::to_string(camera_id));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调整共享内存大小
|
|
|
+ if (ftruncate(shm_fd, SHM_SIZE) == -1) {
|
|
|
+ throw std::runtime_error(
|
|
|
+ "Failed to set size of shared memory for camera " +
|
|
|
+ std::to_string(camera_id));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将共享内存映射到进程地址空间
|
|
|
+ shm_ptr = mmap(0, SHM_SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
|
|
|
+ if (shm_ptr == MAP_FAILED) {
|
|
|
+ throw std::runtime_error("Failed to map shared memory for camera " +
|
|
|
+ std::to_string(camera_id));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建信号量
|
|
|
+ sem = sem_open(sem_name.c_str(), O_CREAT, 0666, 0);
|
|
|
+ if (sem == SEM_FAILED) {
|
|
|
+ throw std::runtime_error("Failed to create semaphore for camera " +
|
|
|
+ std::to_string(camera_id));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Camera::~Camera() {
|
|
|
+ // 释放共享内存
|
|
|
+ if (shm_ptr != nullptr) { munmap(shm_ptr, SHM_SIZE); }
|
|
|
+ if (shm_fd != -1) {
|
|
|
+ close(shm_fd);
|
|
|
+ shm_unlink(shm_name.c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 关闭信号量
|
|
|
+ if (sem != nullptr) {
|
|
|
+ sem_close(sem);
|
|
|
+ sem_unlink(sem_name.c_str());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Camera::start() {
|
|
|
+ cv::Mat frame;
|
|
|
+ while (true) {
|
|
|
+ // 捕获图像
|
|
|
+ cap >> frame;
|
|
|
+ if (frame.empty()) {
|
|
|
+ std::cerr << "Camera " << camera_id << ": Failed to capture frame"
|
|
|
+ << std::endl;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保图像大小符合共享内存
|
|
|
+ if (frame.total() * frame.elemSize() > SHM_SIZE) {
|
|
|
+ std::cerr << "Camera " << camera_id
|
|
|
+ << ": Frame too large for shared memory" << std::endl;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将图像数据拷贝到共享内存
|
|
|
+ std::memcpy(shm_ptr, frame.data, frame.total() * frame.elemSize());
|
|
|
+
|
|
|
+ // 通知其他进程
|
|
|
+ sem_post(sem);
|
|
|
+
|
|
|
+ // 模拟实时相机延迟
|
|
|
+ cv::waitKey(30);
|
|
|
+ }
|
|
|
+}
|
|
|
+}
|