rtsp_tensorrt/pipeline/input/rtsp_reader.cpp
sladro e13cb3659c feat: 初始化项目结构
- 创建基本项目结构和目录
- 添加CMake构建系统
- 实现基础的配置解析功能
- 添加YOLO推理框架支持
- 集成RTSP和视频流处理功能
- 添加性能监控和日志系统
2024-12-24 16:25:03 +08:00

174 lines
4.8 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 "rtsp_reader.hpp"
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
namespace pipeline {
RtspReader::RtspReader(const Config& config)
: config_(config)
, last_frame_time_(std::chrono::steady_clock::now())
, last_retry_time_(std::chrono::steady_clock::now()) {
}
RtspReader::~RtspReader() {
disconnect();
}
bool RtspReader::connect(const std::string& url) {
// 如果已经连接,先断开
if (is_connected_) {
disconnect();
}
// 保存URL
url_ = url;
retry_count_ = 0;
last_retry_time_ = std::chrono::steady_clock::now();
// 如果是模拟源
if (url_.substr(0, 7) == "mock://") {
is_connected_ = true;
mock_frame_ = cv::Mat(480, 640, CV_8UC3, cv::Scalar(0, 255, 0));
cv::putText(mock_frame_, "Test Frame", cv::Point(50, 50),
cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255, 255, 255), 2);
return true;
}
// 设置RTSP流参数并尝试连接
setRtspParams();
return tryReconnect();
}
void RtspReader::disconnect() {
if (is_connected_) {
if (url_.substr(0, 7) != "mock://") {
cap_.release();
}
is_connected_ = false;
retry_count_ = 0; // 重置重试次数
last_retry_time_ = std::chrono::steady_clock::now(); // 重置重试时间
}
}
bool RtspReader::read(cv::Mat& frame) {
if (!is_connected_) {
if (!tryReconnect()) {
return false;
}
}
// 控制帧率
controlFrameRate();
// 如果是模拟源
if (url_.substr(0, 7) == "mock://") {
if (!mock_frame_.empty()) {
frame = mock_frame_.clone();
updateFrameRate();
return true;
}
return false;
}
// 读取一帧(带超时)
bool success = false;
auto start_time = std::chrono::steady_clock::now();
while (std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - start_time).count() < config_.frame_timeout_ms) {
if (cap_.read(frame)) {
success = true;
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
// 读取失败,可能需要重连
if (!success || frame.empty()) {
is_connected_ = false;
return false;
}
// 更新帧率统计
updateFrameRate();
return true;
}
bool RtspReader::tryReconnect() {
// 如果是模拟源
if (url_.substr(0, 7) == "mock://") {
if (mock_frame_.empty()) {
mock_frame_ = cv::Mat(480, 640, CV_8UC3, cv::Scalar(0, 255, 0));
cv::putText(mock_frame_, "Test Frame", cv::Point(50, 50),
cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255, 255, 255), 2);
}
is_connected_ = true;
retry_count_ = 0;
return true;
}
// 检查重试次数和间隔
auto now = std::chrono::steady_clock::now();
if (retry_count_ >= config_.max_retry_count) {
return false;
}
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
now - last_retry_time_).count();
if (elapsed < config_.retry_interval_ms && retry_count_ > 0) {
return false;
}
// 尝试重新打开RTSP流
if (!cap_.open(url_, cv::CAP_FFMPEG)) {
retry_count_++;
last_retry_time_ = now;
return false;
}
// 检查连接是否成功
if (!cap_.isOpened()) {
retry_count_++;
last_retry_time_ = now;
return false;
}
// 连接成功
is_connected_ = true;
retry_count_ = 0;
return true;
}
void RtspReader::updateFrameRate() {
auto now = std::chrono::steady_clock::now();
float delta = std::chrono::duration_cast<std::chrono::milliseconds>(
now - last_frame_time_).count() / 1000.0f;
current_fps_ = 1.0f / delta;
last_frame_time_ = now;
}
void RtspReader::controlFrameRate() {
if (config_.target_fps <= 0) return;
auto now = std::chrono::steady_clock::now();
float target_delta = 1.0f / config_.target_fps;
float actual_delta = std::chrono::duration_cast<std::chrono::milliseconds>(
now - last_frame_time_).count() / 1000.0f;
if (actual_delta < target_delta) {
auto sleep_time = static_cast<int>(
(target_delta - actual_delta) * 1000);
std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
}
}
void RtspReader::setRtspParams() {
// 设置缓冲区大小
cap_.set(cv::CAP_PROP_BUFFERSIZE, config_.buffer_size);
// 设置RTSP相关参数
// 使用MJPEG编码器可以降低延迟
cap_.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M','J','P','G'));
}
} // namespace pipeline