Как правильно завершить работу RTSP-сервера с помощью C++ API?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как правильно завершить работу RTSP-сервера с помощью C++ API?

Сообщение Anonymous »

Я пытаюсь настроить RTSP-сервер, используя API GStreamer для C++. Я хотел бы полностью выключить и перезапустить этот стример по команде. На основе этих примеров (1, 2, 3, 4, 5) мне наконец удалось реализовать конвейер, который, кажется, работает. Тем не менее, я по-прежнему получаю это сообщение об ошибке всякий раз, когда останавливаю RTSP-сервер:

Код: Выделить всё

GLib-GObject-CRITICAL **: 12:53:20.742: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
Вот MWE моего конвейера (RTSPSeverClass.cpp):

Код: Выделить всё

#include 

static gboolean RTSPServerTimeout(GstRTSPServer *RTSPServer) {

if (RTSPServer && GST_IS_RTSP_SERVER(RTSPServer)) {
GstRTSPSessionPool *pool;
pool = gst_rtsp_server_get_session_pool(RTSPServer);
gst_rtsp_session_pool_cleanup(pool);
g_object_unref(pool);
}

return true;
}

GstRTSPFilterResult clientFilterFunc(GstRTSPServer *server, GstRTSPClient *client, gpointer user_data) {
return GST_RTSP_FILTER_REMOVE;
}

RTSPSeverClass::RTSPSeverClass() {
gst_init(nullptr, nullptr);
}

void RTSPSeverClass::RunRTSPLoop() {
g_main_loop_run(RTSPLoop);
}
void RTSPSeverClass::ClientConnected(GstRTSPServer* server, GstRTSPClient* client, gpointer user_data) {
auto* clientCount = reinterpret_cast(user_data);
clientCount->fetch_add(1);
g_signal_connect(client, "closed", reinterpret_cast(RTSPSeverClass::ClientClosed), clientCount);
}

void RTSPSeverClass::ClientClosed(GstRTSPClient* client, gpointer user_data) {
auto* clientCount = reinterpret_cast(user_data);
clientCount->fetch_sub(1);
}

bool RTSPSeverClass::InitializeRTSPServer(const char* ip, const char* port, const char* path, std::string launchString) {

{
std::lock_guard lock(RTSPMutex);

RTSPLoop = g_main_loop_new(nullptr, true);

RTSPServer = gst_rtsp_server_new();
gst_rtsp_server_set_address(RTSPServer, ip);
gst_rtsp_server_set_service(RTSPServer, port);

RTSPFactory = gst_rtsp_media_factory_new();
// gst_rtsp_media_factory_set_eos_shutdown(RTSPFactory, true);
// gst_rtsp_media_factory_set_suspend_mode(RTSPFactory, GST_RTSP_SUSPEND_MODE_RESET);
gst_rtsp_media_factory_set_launch(RTSPFactory, launchString.c_str());
gst_rtsp_media_factory_set_shared(RTSPFactory, true);

RTSPMount = gst_rtsp_server_get_mount_points(RTSPServer);
gst_rtsp_mount_points_add_factory(RTSPMount, path, RTSPFactory);
g_object_unref(RTSPMount);
RTSPMount = nullptr;

RTSPSourceID = gst_rtsp_server_attach(RTSPServer, nullptr);
g_signal_connect(RTSPServer, "client-connected", reinterpret_cast(RTSPSeverClass::ClientConnected), reinterpret_cast(&RTSPClientCount));

g_timeout_add_seconds(2, (GSourceFunc)RTSPServerTimeout, RTSPServer);
}

RTSPThread = std::thread(&RTSPSeverClass::RunRTSPLoop, this);

return true;
}

bool RTSPSeverClass::StopRTSPServer() {
bool success = true;

std::lock_guard lock(RTSPMutex);

if (RTSPLoop) {
g_main_loop_quit(RTSPLoop);
} else {
success = false;
}

if (RTSPThread.joinable()) {
RTSPThread.join();
} else {
success = false;
}

if (RTSPServer && GST_IS_RTSP_SERVER(RTSPServer)) {
if (0 < RTSPClientCount.load()) {
gst_rtsp_server_client_filter(RTSPServer, clientFilterFunc, nullptr);
}

GstRTSPSessionPool *pool = gst_rtsp_server_get_session_pool(RTSPServer);
if (pool && GST_IS_RTSP_SESSION_POOL(pool)) {
gst_rtsp_session_pool_cleanup(pool);
g_object_unref(pool);
} else {
success = false;
}
}

if (RTSPSourceID) {
g_source_remove(RTSPSourceID);
RTSPSourceID = 0;
} else {
success = false;
}

if (RTSPFactory && G_IS_OBJECT(RTSPFactory)) {
g_object_unref(RTSPFactory);
RTSPFactory = nullptr;
} else {
success = false;
}

if (RTSPServer && G_IS_OBJECT(RTSPServer) &&  GST_IS_RTSP_SERVER(RTSPServer)) {
g_object_unref(RTSPServer);
RTSPServer = nullptr;
} else {
success = false;
}

if (RTSPLoop) {
g_main_loop_unref(RTSPLoop);
RTSPLoop = nullptr;
} else {
success = false;
}

// gst_deinit();

return success;
}

bool RTSPSeverClass::ToggleRTSPServer(bool start) {
if (start) {
const char* ip;  // some ip
const char* port;  // some port
const char* path;  // some path
std::string launchString;   // some launch string
InitializeRTSPServer(ip, port, path, launchString);
} else {
StopRTSPServer();
}
}
И для полноты картины, вот еще RTSPSeverClass.hpp:

Код: Выделить всё

#ifndef RTSPSERVERCLASS

#include 
#include 
#include 
#include 
#include 
#include 
#include 

class RTSPSeverClass {
public:

RTSPSeverClass::RTSPSeverClass() {
gst_init(nullptr, nullptr);
}
bool ToggleRTSPServer(bool start);

private:

std::mutex RTSPMutex;
std::thread RTSPThread;
GMainLoop* RTSPLoop;
GstRTSPServer* RTSPServer;
guint RTSPSourceID;
GstRTSPMountPoints* RTSPMount;
GstRTSPMediaFactory* RTSPFactory;
std::atomic RTSPClientCount;

static void ClientClosed(GstRTSPClient* client, gpointer user);
static void ClientConnected(GstRTSPServer* server, GstRTSPClient* client, gpointer user);
void RunRTSPLoop();
bool InitializeRTSPServer(const char* ip, const char* port, const char* path, std::string launchString);
bool StopRTSPServer();
};

#endif
Хотя они, вероятно, не имеют значения, я также включил вспомогательные функции, но важные биты, безусловно, находятся в методах InitializeRTSPServer() и InitializeRTSPServer(). Я обнаружил, что ошибка каким-то образом связана с отменой ссылок на RTSPSourceID, RTSPFactory и RTSPServer, поэтому я включил проверки перед отменой ссылки. Например, если я отменю ссылку только на RTSPFactory или RTSPServer, ошибка исчезнет. Он также исчезает, если я не удаляю RTSPSourceID, однако в этом случае я не могу перезапустить сервер. Так что этот вызов кажется важным.
В целом, кажется, что между вызовами есть некоторое внутреннее перекрытие, т. е. они, кажется, пытаются в какой-то момент отменить ссылку или получить доступ к одному и тому же объекту, который уже был удален предыдущим вызовом. Но я действительно не уверен. Как мне правильно выполнить это выключение?

Подробнее здесь: https://stackoverflow.com/questions/798 ... -the-c-api
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»