first commit
This commit is contained in:
parent
76bdd6f77b
commit
014a5b4b6d
@ -2,6 +2,7 @@
|
|||||||
#include "rtsp_manager.hpp"
|
#include "rtsp_manager.hpp"
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
// 静态变量定义
|
// 静态变量定义
|
||||||
GMainLoop *RTSPManager::loop = nullptr;
|
GMainLoop *RTSPManager::loop = nullptr;
|
||||||
@ -19,6 +20,7 @@ void RTSPManager::init()
|
|||||||
LOG_INFO("[RTSP] GStreamer initialized.");
|
LOG_INFO("[RTSP] GStreamer initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建 media factory
|
||||||
GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam)
|
GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam)
|
||||||
{
|
{
|
||||||
std::string launch_str =
|
std::string launch_str =
|
||||||
@ -32,13 +34,14 @@ GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam)
|
|||||||
gst_rtsp_media_factory_set_launch(factory, launch_str.c_str());
|
gst_rtsp_media_factory_set_launch(factory, launch_str.c_str());
|
||||||
gst_rtsp_media_factory_set_shared(factory, TRUE);
|
gst_rtsp_media_factory_set_shared(factory, TRUE);
|
||||||
|
|
||||||
// 连接 media-created 信号,跟踪媒体对象
|
// 使用 media-configure 信号代替 media-created
|
||||||
g_signal_connect_data(factory, "media-created", G_CALLBACK(on_media_created), g_strdup(cam.name.c_str()),
|
g_signal_connect_data(factory, "media-configure", G_CALLBACK(on_media_created),
|
||||||
(GClosureNotify)g_free, static_cast<GConnectFlags>(0));
|
g_strdup(cam.name.c_str()), (GClosureNotify)g_free, static_cast<GConnectFlags>(0));
|
||||||
|
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 启动 RTSP server
|
||||||
void RTSPManager::start(const std::vector<Camera> &cameras)
|
void RTSPManager::start(const std::vector<Camera> &cameras)
|
||||||
{
|
{
|
||||||
server = gst_rtsp_server_new();
|
server = gst_rtsp_server_new();
|
||||||
@ -62,38 +65,44 @@ void RTSPManager::start(const std::vector<Camera> &cameras)
|
|||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
loop = nullptr;
|
loop = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("[RTSP] Server stopped.");
|
LOG_INFO("[RTSP] Server stopped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 媒体创建信号处理函数
|
// media-configure 信号处理
|
||||||
void RTSPManager::on_media_created(GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data)
|
void RTSPManager::on_media_created(GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data)
|
||||||
{
|
{
|
||||||
const char *cam_name = static_cast<const char *>(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_object_ref(media); // 增加引用计数,防止被提前销毁
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(media_map_mutex);
|
||||||
|
media_map[cam_name].push_back(media);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 连接 unprepared 信号,当 pipeline 被销毁时移除
|
||||||
g_signal_connect_data(media, "unprepared", G_CALLBACK(on_media_unprepared),
|
g_signal_connect_data(media, "unprepared", G_CALLBACK(on_media_unprepared),
|
||||||
g_strdup(cam_name), (GClosureNotify)g_free, static_cast<GConnectFlags>(0));
|
g_strdup(cam_name), (GClosureNotify)g_free, static_cast<GConnectFlags>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 媒体 unprepared 信号处理函数
|
// unprepared 信号处理
|
||||||
void RTSPManager::on_media_unprepared(GstRTSPMedia *media, gpointer user_data)
|
void RTSPManager::on_media_unprepared(GstRTSPMedia *media, gpointer user_data)
|
||||||
{
|
{
|
||||||
const char *cam_name = static_cast<const char *>(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;
|
std::lock_guard<std::mutex> lock(media_map_mutex);
|
||||||
media_list.erase(std::remove(media_list.begin(), media_list.end(), media), media_list.end());
|
auto it = media_map.find(cam_name);
|
||||||
if (media_list.empty())
|
if (it != media_map.end())
|
||||||
{
|
{
|
||||||
media_map.erase(it);
|
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 中增加的引用
|
g_object_unref(media); // 释放引用
|
||||||
}
|
}
|
||||||
|
|
||||||
// 挂载摄像头
|
// 挂载摄像头
|
||||||
@ -136,7 +145,7 @@ gboolean RTSPManager::mount_camera_in_main(gpointer data)
|
|||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 卸载摄像头(停止所有媒体会话)
|
// 卸载摄像头
|
||||||
gboolean RTSPManager::unmount_camera_in_main(gpointer data)
|
gboolean RTSPManager::unmount_camera_in_main(gpointer data)
|
||||||
{
|
{
|
||||||
Camera *cam = static_cast<Camera *>(data);
|
Camera *cam = static_cast<Camera *>(data);
|
||||||
@ -145,11 +154,26 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data)
|
|||||||
delete cam;
|
delete cam;
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cam_name = cam->name;
|
std::string cam_name = cam->name;
|
||||||
std::string mount_point = "/" + cam_name;
|
std::string mount_point = "/" + cam_name;
|
||||||
|
|
||||||
// 卸载 factory(自动断开客户端)
|
// 停止所有媒体
|
||||||
|
{
|
||||||
|
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_element_set_state(gst_rtsp_media_get_element(media), GST_STATE_NULL);
|
||||||
|
g_object_unref(media);
|
||||||
|
}
|
||||||
|
it->second.clear();
|
||||||
|
media_map.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 卸载 factory
|
||||||
GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server);
|
GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server);
|
||||||
if (mounts)
|
if (mounts)
|
||||||
{
|
{
|
||||||
@ -157,13 +181,6 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data)
|
|||||||
g_object_unref(mounts);
|
g_object_unref(mounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清理 media_map
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(media_map_mutex);
|
|
||||||
media_map.erase(cam_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 释放 factory 对象
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mounted_factories_mutex);
|
std::lock_guard<std::mutex> lock(mounted_factories_mutex);
|
||||||
auto it = mounted_factories.find(cam_name);
|
auto it = mounted_factories.find(cam_name);
|
||||||
@ -181,6 +198,7 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data)
|
|||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 公共挂载/卸载接口
|
||||||
void RTSPManager::mount_camera(const Camera &cam)
|
void RTSPManager::mount_camera(const Camera &cam)
|
||||||
{
|
{
|
||||||
Camera *camCopy = new Camera(cam);
|
Camera *camCopy = new Camera(cam);
|
||||||
@ -195,6 +213,7 @@ void RTSPManager::unmount_camera(const Camera &cam)
|
|||||||
{ return RTSPManager::unmount_camera_in_main(data); }, camCopy);
|
{ return RTSPManager::unmount_camera_in_main(data); }, camCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 是否正在流
|
||||||
bool RTSPManager::is_streaming(const std::string &cam_name)
|
bool RTSPManager::is_streaming(const std::string &cam_name)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mounted_factories_mutex);
|
std::lock_guard<std::mutex> lock(mounted_factories_mutex);
|
||||||
@ -202,13 +221,14 @@ bool RTSPManager::is_streaming(const std::string &cam_name)
|
|||||||
return it != streaming_status.end() ? it->second : false;
|
return it != streaming_status.end() ? it->second : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 停止 server
|
||||||
void RTSPManager::stop()
|
void RTSPManager::stop()
|
||||||
{
|
{
|
||||||
if (loop)
|
if (loop)
|
||||||
{
|
{
|
||||||
g_main_context_invoke(main_context, [](gpointer data) -> gboolean
|
g_main_context_invoke(main_context, [](gpointer data) -> gboolean
|
||||||
{
|
{
|
||||||
g_main_loop_quit(static_cast<GMainLoop *>(data));
|
g_main_loop_quit(static_cast<GMainLoop *>(data));
|
||||||
return G_SOURCE_REMOVE; }, loop);
|
return G_SOURCE_REMOVE; }, loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user