rtsp_tensorrt/tests/test_output_manager.cpp

251 lines
7.9 KiB
C++

#include <gtest/gtest.h>
#include <filesystem>
#include <thread>
#include <chrono>
#include "pipeline/output/output_manager.hpp"
#include "pipeline/common/logger.hpp"
namespace fs = std::filesystem;
namespace pipeline {
class OutputManagerTest : public ::testing::Test {
protected:
void SetUp() override {
// 创建测试目录
test_dir_ = "/tmp/test_output_manager";
if (fs::exists(test_dir_)) {
fs::remove_all(test_dir_);
}
fs::create_directories(test_dir_);
// 创建测试帧
test_frame_ = cv::Mat(480, 640, CV_8UC3, cv::Scalar(0, 0, 0));
}
void TearDown() override {
if (fs::exists(test_dir_)) {
fs::remove_all(test_dir_);
}
}
// 创建视频输出配置
OutputTargetConfig createVideoConfig(const std::string& name) {
OutputTargetConfig config;
config.type = "video";
config.name = name;
config.path = test_dir_ + "/" + name + ".mp4";
config.fps = 30;
config.codec = "h264";
config.bitrate = 4000000;
return config;
}
// 创建RTSP输出配置
OutputTargetConfig createRtspConfig(const std::string& name) {
OutputTargetConfig config;
config.type = "rtsp";
config.name = name;
config.path = "rtsp://localhost:8554/" + name;
config.fps = 30;
config.codec = "h264";
config.bitrate = 4000000;
return config;
}
std::string test_dir_;
cv::Mat test_frame_;
};
// 测试基本功能
TEST_F(OutputManagerTest, BasicFunctionality) {
OutputManager manager;
// 添加输出目标
auto video_config = createVideoConfig("test_video");
EXPECT_TRUE(manager.addTarget(video_config));
auto rtsp_config = createRtspConfig("test_rtsp");
EXPECT_TRUE(manager.addTarget(rtsp_config));
// 验证目标数量
EXPECT_EQ(manager.getTargetCount(), 2);
// 验证目标名称
auto names = manager.getTargetNames();
EXPECT_EQ(names.size(), 2);
EXPECT_TRUE(std::find(names.begin(), names.end(), "test_video") != names.end());
EXPECT_TRUE(std::find(names.begin(), names.end(), "test_rtsp") != names.end());
}
// 测试输入源到输出目标的映射
TEST_F(OutputManagerTest, SourceTargetMapping) {
OutputManager manager;
// 添加视频输出目标
OutputTargetConfig video_config;
video_config.type = "video";
video_config.name = "test_video_map";
video_config.path = "/tmp/test_output_manager/test_video_map.mp4";
ASSERT_TRUE(manager.addTarget(video_config));
// 添加源到目标的映射
ASSERT_TRUE(manager.addSourceTargetMapping("source1", {"test_video_map"}));
// 写入帧
ASSERT_TRUE(manager.writeFrames("source1", test_frame_));
// 验证输出文件存在
ASSERT_TRUE(fs::exists(video_config.path));
}
// 测试错误处理
TEST_F(OutputManagerTest, ErrorHandling) {
OutputManager manager;
// 测试添加重复目标
auto video_config = createVideoConfig("test_video_error");
EXPECT_TRUE(manager.addTarget(video_config));
EXPECT_FALSE(manager.addTarget(video_config));
// 测试无效的映射
std::vector<std::string> targets = {"non_existent_target"};
EXPECT_FALSE(manager.addSourceTargetMapping("source", targets));
// 测试写入不存在的源
EXPECT_FALSE(manager.writeFrames("non_existent_source", test_frame_));
// 测试空帧
cv::Mat empty_frame;
EXPECT_FALSE(manager.writeFrames("source", empty_frame));
}
// 测试资源管理
TEST_F(OutputManagerTest, ResourceManagement) {
OutputManager manager;
// 添加多个目标
auto video_config = createVideoConfig("test_video_resource");
EXPECT_TRUE(manager.addTarget(video_config));
auto rtsp_config = createRtspConfig("test_rtsp_resource");
EXPECT_TRUE(manager.addTarget(rtsp_config));
// 添加映射
std::vector<std::string> targets = {"test_video_resource", "test_rtsp_resource"};
EXPECT_TRUE(manager.addSourceTargetMapping("source", targets));
// 移除映射
EXPECT_TRUE(manager.removeSourceMapping("source"));
EXPECT_FALSE(manager.writeFrames("source", test_frame_));
// 移除目标
EXPECT_TRUE(manager.removeTarget("test_video_resource"));
EXPECT_EQ(manager.getTargetCount(), 1);
// 清理所有资源
manager.cleanup();
EXPECT_EQ(manager.getTargetCount(), 0);
}
// 测试并发写入
TEST_F(OutputManagerTest, ConcurrentWrite) {
OutputManager manager;
// 添加两个视频输出目标
auto video_config1 = createVideoConfig("test_video_concurrent1");
ASSERT_TRUE(manager.addTarget(video_config1));
auto video_config2 = createVideoConfig("test_video_concurrent2");
ASSERT_TRUE(manager.addTarget(video_config2));
// 添加源到目标的映射
ASSERT_TRUE(manager.addSourceTargetMapping("source1", {"test_video_concurrent1"}));
ASSERT_TRUE(manager.addSourceTargetMapping("source2", {"test_video_concurrent2"}));
// 创建两个线程同时写入不同的输出目标
std::thread t1([&]() {
for (int i = 0; i < 10; ++i) {
EXPECT_TRUE(manager.writeFrames("source1", test_frame_));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
});
std::thread t2([&]() {
for (int i = 0; i < 10; ++i) {
EXPECT_TRUE(manager.writeFrames("source2", test_frame_));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
});
// 等待线程完成
t1.join();
t2.join();
// 验证输出文件存在
ASSERT_TRUE(fs::exists(video_config1.path));
ASSERT_TRUE(fs::exists(video_config2.path));
}
// 测试一个输入源映射到多个输出目标
TEST_F(OutputManagerTest, MultipleTargetsMapping) {
OutputManager manager;
// 添加多个输出目标
auto video_config1 = createVideoConfig("test_video_multi1");
ASSERT_TRUE(manager.addTarget(video_config1));
auto video_config2 = createVideoConfig("test_video_multi2");
ASSERT_TRUE(manager.addTarget(video_config2));
auto video_config3 = createVideoConfig("test_video_multi3");
ASSERT_TRUE(manager.addTarget(video_config3));
// 将一个输入源映射到多个输出目标
std::vector<std::string> targets = {
"test_video_multi1",
"test_video_multi2",
"test_video_multi3"
};
ASSERT_TRUE(manager.addSourceTargetMapping("source_multi", targets));
// 写入帧到所有映射的目标
ASSERT_TRUE(manager.writeFrames("source_multi", test_frame_));
// 验证所有输出文件都存在
ASSERT_TRUE(fs::exists(video_config1.path));
ASSERT_TRUE(fs::exists(video_config2.path));
ASSERT_TRUE(fs::exists(video_config3.path));
}
// 测试FPS参数边界值
TEST_F(OutputManagerTest, FpsBoundaryTest) {
OutputManager manager;
// 测试FPS为0
auto config_fps_zero = createVideoConfig("test_video_fps_zero");
config_fps_zero.fps = 0;
EXPECT_FALSE(manager.addTarget(config_fps_zero));
// 测试FPS为负数
auto config_fps_negative = createVideoConfig("test_video_fps_negative");
config_fps_negative.fps = -30;
EXPECT_FALSE(manager.addTarget(config_fps_negative));
// 测试FPS为最小有效值
auto config_fps_min = createVideoConfig("test_video_fps_min");
config_fps_min.fps = 1;
EXPECT_TRUE(manager.addTarget(config_fps_min));
// 测试FPS为正常值
auto config_fps_normal = createVideoConfig("test_video_fps_normal");
config_fps_normal.fps = 60;
EXPECT_TRUE(manager.addTarget(config_fps_normal));
// 验证正常FPS的输出是否工作
ASSERT_TRUE(manager.addSourceTargetMapping("source_fps", {"test_video_fps_normal"}));
ASSERT_TRUE(manager.writeFrames("source_fps", test_frame_));
ASSERT_TRUE(fs::exists(config_fps_normal.path));
}
} // namespace pipeline