diff --git a/capture.cc b/capture.cc index 63d3653..359328b 100644 --- a/capture.cc +++ b/capture.cc @@ -27,12 +27,12 @@ capture::capture(int camera_index, int zmq_port, int width_set, int height_set, if (!cap->isOpened()) { - log_error("Error opening video stream in %d", index); + log_error("开启摄像头 %d 失败", index); status = false; } else { - log_info("Successful opening video stream in %d", index); + log_info("开启摄像头 %d 成功", index); status = true; } @@ -43,7 +43,7 @@ capture::capture(int camera_index, int zmq_port, int width_set, int height_set, char zmq_bind_port[10] = {0}; sprintf(zmq_bind_port, "%d", port); strcat(zmq_bind_addr, zmq_bind_port); - log_info("set camera %d zmq address test %s", index, zmq_bind_addr); + log_info("设置 %d zmq 地址 %s", index, zmq_bind_addr); socket->bind(zmq_bind_addr); } @@ -51,68 +51,73 @@ void capture::start(void) { if (this->is_open()) { - log_info("start camera %d capture thread", index); - thread = new std::thread(&capture::run, this); + log_info("开启摄像头 %d 采集和应答线程", index); + // FIXME request 启动后若 capture 尚未读取到有效帧,则会断言 + thread_capture = new std::thread(&capture::get, this); + sleep(1); + thread_request = new std::thread(&capture::req, this); } else { - log_error("camera %d have not been inited, exit", index); + log_error("摄像头 %d 未成功初始化,跳过", index); } } -void capture::run(void) +void capture::get(void) { cv::Mat dst; while (1) { - zmq::message_t msg_temp; - socket->recv(&msg_temp); - *cap >> frame; - if (frame.empty()) + *cap >> dst; + if (dst.empty()) { - // TODO 尝试返回缓存帧,并重新启动 capture - log_error("empty frame"); - break; + log_error("摄像头 %d 读取到空帧,尝试销毁后重启", index); + + cap->release(); + // delete cap; + + cap = new cv::VideoCapture(index, cv::CAP_V4L2); + cap->set(cv::CAP_PROP_FRAME_WIDTH, width); + cap->set(cv::CAP_PROP_FRAME_HEIGHT, height); + cap->set(cv::CAP_PROP_FPS, fps); + + log_warn("摄像头 %d 重新构造完成\r\n", index); + *cap >> dst; } // 确保图像是连续的 - if (!frame.isContinuous()) + if (!dst.isContinuous()) { - frame = frame.clone().reshape(1, frame.total()); + dst = dst.clone().reshape(1, dst.total()); } // 中心翻转处理 if (flip) { - cv::flip(frame, frame, -1); + cv::flip(dst, dst, -1); } // 将图像转换为 rgb - cv::cvtColor(frame, dst, cv::COLOR_BGR2RGB); + cv::cvtColor(dst, frame, cv::COLOR_BGR2RGB); + // 在这里添加一些延迟,以控制帧率 + cv::waitKey(1); + } +} + +void capture::req(void) +{ + zmq::message_t msg_temp; + while (1) + { + socket->recv(&msg_temp); // 将帧编码后发送 std::vector buff; - cv::imencode(".jpg", dst, buff); + cv::imencode(".jpg", frame, buff); zmq::message_t message(buff.size()); memcpy(message.data(), buff.data(), buff.size()); socket->send(message, zmq::send_flags::none); - - // 发送帧的元数据(宽度、高度、类型等) - // 这里简单起见,只发送宽度和高度(假设类型为 CV_8UC3) - // zmq::message_t header_msg(sizeof(int) * 2); - // int *header_data = static_cast(header_msg.data()); - // header_data[0] = frame.cols; - // header_data[1] = frame.rows; - // socket.send(header_msg, zmq::send_flags::sndmore); - - // 发送帧数据 - // zmq::message_t frame_msg((size_t)frame.total() * frame.elemSize()); - // memcpy(frame_msg.data(), frame.data, frame.total() * frame.elemSize()); - // socket->send(frame_msg, zmq::send_flags::none); - // 在这里添加一些延迟,以控制帧率 - cv::waitKey(1); - // usleep(20000); } log_error("capture exit"); diff --git a/capture.h b/capture.h index 61db060..1ecbe7e 100644 --- a/capture.h +++ b/capture.h @@ -18,7 +18,8 @@ public: bool flip = false; char zmq_bind_addr[40] = "tcp://*:"; - std::thread *thread; + std::thread *thread_capture; + std::thread *thread_request; cv::VideoCapture *cap; cv::Mat frame; zmq::context_t *context; @@ -26,7 +27,8 @@ public: capture(int camera_index, int zmq_port, int width_set = 320, int height_set = 240, int fps_set = 20, bool flip = false); void start(void); - void run(void); + void get(void); + void req(void); bool is_open(void); }; diff --git a/main.cc b/main.cc index 5fbd6a1..66f0842 100644 --- a/main.cc +++ b/main.cc @@ -48,62 +48,13 @@ int main(int argc, char **argv) capture cap0(server_0_index.u.i, server_0_port.u.i); capture cap1(server_1_index.u.i, server_1_port.u.i, 320, 240, 60, true); - // capture cap2(server_2_index.u.i, server_2_port.u.i); + // capture cap2(server_2_index.u.i, server_2_port.u.i, 640, 480); cap0.start(); cap1.start(); // cap2.start(); - if (cap0.is_open()) - { - cap0.thread->join(); - } - if (cap1.is_open()) - { - cap1.thread->join(); - } - // if (cap2.is_open()) - // { - // cap2.thread->join(); - // } - - // while (true) - // { - // cap >> frame; - // if (frame.empty()) - // { - // std::cerr << "Empty frame" << std::endl; - // break; - // } - - // // 确保图像是连续的 - // if (!frame.isContinuous()) - // { - // frame = frame.clone().reshape(1, frame.total()); - // } - - // // std::cout << frame.cols << ":" << frame.rows << std::endl; - - // // cv::imshow("realtime", frame); - - // // 发送帧的元数据(宽度、高度、类型等) - // // 这里简单起见,只发送宽度和高度(假设类型为 CV_8UC3) - // zmq::message_t header_msg(sizeof(int) * 2); - // int *header_data = static_cast(header_msg.data()); - // header_data[0] = frame.cols; - // header_data[1] = frame.rows; - // // socket.send(header_msg, zmq::send_flags::sndmore); - - // // 发送帧数据 - // zmq::message_t frame_msg((size_t)frame.total() * frame.elemSize()); - // memcpy(frame_msg.data(), frame.data, frame.total() * frame.elemSize()); - // socket.send(frame_msg, zmq::send_flags::none); - // // 在这里添加一些延迟,以控制帧率 - // cv::waitKey(1); - // } - - // // 关闭视频捕获和 ZMQ 套接字 - // cap.release(); - // socket.close(); + cap1.thread_request->join(); + return 0; } \ No newline at end of file