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;