Files
project_capture/capture.cc
2024-07-01 01:30:45 +08:00

124 lines
3.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "capture.h"
#include <vector>
#include <thread>
#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <zmq.hpp>
#include "logc/log.h"
#include <unistd.h>
capture::capture(int camera_index, int zmq_port, int width_set, int height_set, int fps_set, bool _flip)
{
index = camera_index;
port = zmq_port;
width = width_set;
height = height_set;
fps = fps_set;
flip = _flip;
log_info("trying open camera %d", index);
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);
if (!cap->isOpened())
{
log_error("Error opening video stream in %d", index);
status = false;
}
else
{
log_info("Successful opening video stream in %d", index);
status = true;
}
context = new zmq::context_t(1);
socket = new zmq::socket_t(*context, ZMQ_REP);
// int hwm = 10;
// socket->setsockopt(ZMQ_SNDHWM, &hwm, sizeof(hwm));
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);
socket->bind(zmq_bind_addr);
}
void capture::start(void)
{
if (this->is_open())
{
log_info("start camera %d capture thread", index);
thread = new std::thread(&capture::run, this);
}
else
{
log_error("camera %d have not been inited, exit", index);
}
}
void capture::run(void)
{
cv::Mat dst;
while (1)
{
zmq::message_t msg_temp;
socket->recv(&msg_temp);
*cap >> frame;
if (frame.empty())
{
// TODO 尝试返回缓存帧,并重新启动 capture
log_error("empty frame");
break;
}
// 确保图像是连续的
if (!frame.isContinuous())
{
frame = frame.clone().reshape(1, frame.total());
}
// 中心翻转处理
if (flip)
{
cv::flip(frame, frame, -1);
}
// 将图像转换为 rgb
cv::cvtColor(frame, dst, cv::COLOR_BGR2RGB);
// 将帧编码后发送
std::vector<uchar>
buff;
cv::imencode(".jpg", dst, 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<int *>(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");
}
bool capture::is_open(void)
{
return status;
}