Live555 - правильное отключение клиента с помощью watchVariable

У меня сейчас проблема с live555.

Я написал Windows DLL для своего проекта, эта DLL предоставляет очень простой API для легкого запуска RTSP-клиента. Программа Unity загружает DLL, а затем использует API для получения фреймов.

две основные функции:

bool startRTSP(bool isTCP);
bool stopRTSP();

Из-за особенностей библиотеки Live555 я не могу запустить RTSP в потоке Unity. Поэтому я создал новый поток, когда вызывается startRTSP, и с некоторыми обратными вызовами кадры отправляются в единицу.

Тем не менее, чтобы иметь возможность остановить RTSP из внешнего потока (поток единства, вызывающий stopRTSP), я использую eventLoopWatchVariable. Например, вот как запускается цикл событий RTSP:

env->taskScheduler().doEventLoop(&eventLoopWatchVariable);

Когда вызывается функция остановки, eventLoopWatchVariable устанавливается в 1 из потока единицы. Завершение цикла Loop.

Сразу после выхода из цикла обработки событий вызываются функции очистки:

delete scheduler;
env->reclaim();

Я ожидал, что функция thoose пройдет через RTSP-клиент и отключит его. (Отправка команды TEARDOWN на сервер, например)

Но они явно не делают, и клиенты никогда не уничтожаются!

Я подозреваю, что это вызовет проблему повторного обращения в том же потоке. (команды SETUP, DESCRIBE и PLAY отправлены и ответы получены, но данные не поступают). Используя VLC или mplayer, я могу видеть, что сервер все еще выполняет потоковую передачу, так что это не проблема сервера.

Как я могу попросить live555 закрыть RTSPClient и его подразделения, когда для eventLoopWatchVariable установлено значение 1?

Я не могу отправить команду TEARDOWN на сервер, если eventLoop больше не работает. Так что сейчас я немного растерялся из-за лучшего способа сделать это.

Если у кого-то есть идея об этом, я хотел бы услышать это!

Заранее спасибо.

1 ответ

Я не могу отправить команду TEARDOWN на сервер, если eventLoop больше не работает.

Это неточно, основной цикл необходим для получения сообщений, а не для отправки сообщений.

Чтобы правильно закрыть клиентское соединение RTSP после основного цикла и перед освобождением среды, вы могли бы действовать следующим образом:

// wait for stop event
env->taskScheduler().doEventLoop(&eventLoopWatchVariable);

// send tear TEARDOWN
client->sendTeardownCommand(session, NULL);

// close subsession & session
Medium::close(session);

// close RTSP client
Medium::close(client);

// free environment & scheduler
env->reclaim();
delete scheduler;

Вы также можете дождаться ответа TEARDOWN, отправив обратный вызов sendTeardownCommand и снова запустив doEventLoop.

Вот правильный способ полностью выключить клиент RTSP. В этом ответе предполагается, что вы используете следующую программу в качестве базы для своего клиента rtsp: testProgs/testRTSPClient.cpp (в комплекте с live555).

Во-первых, измените openURL() так, чтобы он возвращал "RTSPClient* rtspClient" вызывающей стороне. Затем используйте этот пример (продолжение main() внутри testRTSPClient.cpp):

RTSPClient* rtspClient = openURL(*env, argv[0], argv[1]);

// All subsequent activity takes place within the event loop:
env->taskScheduler().doEventLoop(&eventLoopWatchVariable);

//... do whatever stuff you want to do in the background...

//start this code when you want to stop the rtsp client
eventLoopWatchVariable = 1;

//run this code for each rtspClient that exists
StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs;

rtspClient->sendTeardownCommand(*scs.session, NULL);

Medium::close(client->rtspClient);
//end code segment

env->reclaim();
env = NULL;
delete scheduler;
scheduler = NULL;
Другие вопросы по тегам