first commit

This commit is contained in:
cxh 2025-09-09 13:28:05 +08:00
parent 5a0a62ee16
commit d98f8d3f66
2 changed files with 71 additions and 6 deletions

View File

@ -1,3 +1,4 @@
// rtsp_manager.hpp
#pragma once
#include <gst/gst.h>
@ -6,6 +7,7 @@
#include <unordered_map>
#include <string>
#include <mutex>
#include <vector>
class RTSPManager
{
@ -34,4 +36,12 @@ private:
// 静态 mutex 和工厂表
static std::unordered_map<std::string, GstRTSPMediaFactory *> mounted_factories;
static std::mutex mounted_factories_mutex;
// 媒体对象跟踪
static std::unordered_map<std::string, std::vector<GstRTSPMedia *>> media_map;
static std::mutex media_map_mutex;
// 信号处理函数
static void on_media_created(GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data);
static void on_media_unprepared(GstRTSPMedia *media, gpointer user_data);
};

View File

@ -1,3 +1,4 @@
// rtsp_manager.cpp
#include "rtsp_manager.hpp"
#include "logger.hpp"
#include <iostream>
@ -9,6 +10,8 @@ GstRTSPServer *RTSPManager::server = nullptr;
std::unordered_map<std::string, bool> RTSPManager::streaming_status;
std::unordered_map<std::string, GstRTSPMediaFactory *> RTSPManager::mounted_factories;
std::mutex RTSPManager::mounted_factories_mutex;
std::unordered_map<std::string, std::vector<GstRTSPMedia *>> RTSPManager::media_map;
std::mutex RTSPManager::media_map_mutex;
void RTSPManager::init()
{
@ -28,6 +31,11 @@ GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam)
GstRTSPMediaFactory *factory = gst_rtsp_media_factory_new();
gst_rtsp_media_factory_set_launch(factory, launch_str.c_str());
gst_rtsp_media_factory_set_shared(factory, TRUE);
// 连接 media-created 信号,跟踪媒体对象
g_signal_connect_data(factory, "media-created", G_CALLBACK(on_media_created), g_strdup(cam.name.c_str()),
(GClosureNotify)g_free, 0);
return factory;
}
@ -57,6 +65,36 @@ void RTSPManager::start(const std::vector<Camera> &cameras)
LOG_INFO("[RTSP] Server stopped.");
}
// 媒体创建信号处理函数
void RTSPManager::on_media_created(GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data)
{
const char *cam_name = static_cast<const char *>(user_data);
std::lock_guard<std::mutex> lock(media_map_mutex);
media_map[cam_name].push_back(media);
g_object_ref(media); // 增加引用计数,防止意外销毁
// 连接 unprepared 信号,以便在媒体销毁时从列表中移除
g_signal_connect_data(media, "unprepared", G_CALLBACK(on_media_unprepared), g_strdup(cam_name), (GClosureNotify)g_free, 0);
}
// 媒体 unprepared 信号处理函数
void RTSPManager::on_media_unprepared(GstRTSPMedia *media, gpointer user_data)
{
const char *cam_name = static_cast<const char *>(user_data);
std::lock_guard<std::mutex> lock(media_map_mutex);
auto it = media_map.find(cam_name);
if (it != media_map.end())
{
auto &media_list = it->second;
media_list.erase(std::remove(media_list.begin(), media_list.end(), media), media_list.end());
if (media_list.empty())
{
media_map.erase(it);
}
}
g_object_unref(media); // 释放我们在 on_media_created 中增加的引用
}
// 挂载摄像头
gboolean RTSPManager::mount_camera_in_main(gpointer data)
{
@ -97,7 +135,7 @@ gboolean RTSPManager::mount_camera_in_main(gpointer data)
return G_SOURCE_REMOVE;
}
// 卸载摄像头(发送 EOS 停止 pipeline
// 卸载摄像头(停止所有媒体会话
gboolean RTSPManager::unmount_camera_in_main(gpointer data)
{
Camera *cam = static_cast<Camera *>(data);
@ -107,27 +145,44 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data)
return G_SOURCE_REMOVE;
}
std::string cam_name = cam->name;
std::string mount_point = "/" + cam_name;
// 停止所有相关的媒体会话
{
std::lock_guard<std::mutex> lock(media_map_mutex);
auto it = media_map.find(cam_name);
if (it != media_map.end())
{
for (GstRTSPMedia *media : it->second)
{
gst_rtsp_media_stop(media);
}
it->second.clear();
media_map.erase(it);
}
}
GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server);
if (mounts)
{
std::string mount_point = "/" + cam->name;
gst_rtsp_mount_points_remove_factory(mounts, mount_point.c_str());
g_object_unref(mounts);
}
{
std::lock_guard<std::mutex> lock(mounted_factories_mutex);
auto it = mounted_factories.find(cam->name);
auto it = mounted_factories.find(cam_name);
if (it != mounted_factories.end())
{
if (it->second && G_IS_OBJECT(it->second))
g_object_unref(it->second); // 安全 unref
mounted_factories.erase(it);
}
streaming_status[cam->name] = false;
streaming_status[cam_name] = false;
}
LOG_INFO("[RTSP] Camera '" + cam->name + "' unmounted.");
LOG_INFO("[RTSP] Camera '" + cam_name + "' unmounted.");
delete cam;
return G_SOURCE_REMOVE;
}